Поймать несколько исключений в одной строке (кроме блока)

avatar
inspectorG4dget
24 июня 2011 в 15:55
1097271
6
3293

Я знаю, что умею:

try:
    # do something that may fail
except:
    # do this if ANYTHING goes wrong

Я тоже могу это сделать:

try:
    # do something that may fail
except IDontLikeYouException:
    # say please
except YouAreTooShortException:
    # stand on a ladder

Но если я хочу сделать то же самое внутри двух разных исключений, лучшее, что я могу придумать прямо сейчас, - это сделать следующее:

try:
    # do something that may fail
except IDontLikeYouException:
    # say please
except YouAreBeingMeanException:
    # say please

Есть ли способ сделать что-то подобное (поскольку действие, которое нужно предпринять в обоих исключениях, - say please):

try:
    # do something that may fail
except IDontLikeYouException, YouAreBeingMeanException:
    # say please

Теперь это действительно не сработает, так как он соответствует синтаксису для:

try:
    # do something that may fail
except Exception, e:
    # say please

Итак, моя попытка поймать два разных исключения не совсем удалась.

Есть способ сделать это?

Источник
gerrit
17 апреля 2019 в 14:01
19

Обратите внимание, что в Python 3 последний больше не является допустимым синтаксисом.

Ответы (6)

avatar
mechanical_meat
24 июня 2011 в 15:56
4446

Из Документация Python:

Предложение except может называть несколько исключений в виде кортежа в скобках, например

except (IDontLikeYouException, YouAreBeingMeanException) as e:
    pass

Или, только для Python 2:

except (IDontLikeYouException, YouAreBeingMeanException), e:
    pass

Отделение исключения от переменной запятой по-прежнему будет работать в Python 2.6 и 2.7, но теперь устарело и не работает в Python 3; теперь вы должны использовать as.

BallpointBen
22 марта 2018 в 03:04
1

Можно ли сохранить желаемые исключения в итерации, а затем перехватить итерацию? Я пытаюсь превратить список предупреждений в ошибки, используя warnings.filterwarnings, и мне не нужно указывать список предупреждений дважды.

BallpointBen
22 марта 2018 в 16:02
18

Я попробовал ... с list, и это привело к TypeError. Похоже, что ошибки должны быть в tuple, чтобы отлов работал должным образом.

BallpointBen
22 марта 2018 в 16:48
11

Было неясно, был ли «заключенный в скобки кортеж» чисто синтаксическим или требовался добросовестный кортеж. «Заключение в скобки» вводит в заблуждение, потому что вы можете создать кортеж без скобок в другом месте, а затем использовать его в строке except. Он обязательно заключен в скобки, только если он создан в строке except.

Joseph Bani
25 февраля 2019 в 07:27
0

Все, что заключено в скобки в python, является кортежем

jammertheprogrammer
12 апреля 2019 в 00:09
8

@JosephBani, а как насчет выражений генератора?

Soren Bjornstad
12 июля 2019 в 20:25
31

@JosephBani Это совсем не так. В 2 + (x * 2) (x * 2) определенно не кортеж. Скобки - это общая группирующая конструкция. Определяющей характеристикой кортежа является то, что он содержит запятую - см. документацию Python: «Обратите внимание, что на самом деле кортеж образует запятая, а не круглые скобки».

fantabolous
25 октября 2019 в 07:24
1

Когда вы на самом деле не используете e (как в этом случае), вы можете просто отбросить as e или , e, и тогда python 2 и 3 будут одинаковыми;)

Chris Norris
14 февраля 2020 в 22:59
1

Так почему же (кроме ValueError ИЛИ IndexError :) не работает? Это то, что я изначально пробовал, но казалось, что обращалась только к первой ошибке.

mechanical_meat
14 февраля 2020 в 23:01
1

@ChrisNorris: or сложно. В этом примере IndexError ни к чему не привязан, поэтому просто игнорируется.

avatar
Giorgos Myrianthous
2 апреля 2022 в 00:09
4

Начиная с Python 3.11 вы можете воспользоваться предложением except*, которое используется для обработки нескольких исключений.

PEP-654 представил новый стандартный тип исключения, названный ExceptionGroup, который соответствует группе исключений, которые распространяются вместе. ExceptionGroup можно обрабатывать с помощью нового синтаксиса except*. Символ * указывает, что каждое предложение except* может обрабатывать несколько исключений.


Например, вы можете обрабатывать несколько исключений

try:
    raise ExceptionGroup('Example ExceptionGroup', (
        TypeError('Example TypeError'),
        ValueError('Example ValueError'),
        KeyError('Example KeyError'),
        AttributeError('Example AttributeError')
    ))
except* TypeError:
    ...
except* ValueError as e:
    ...
except* (KeyError, AttributeError) as e:
    ...

Подробнее см. PEP-654.

avatar
whitebeard
18 сентября 2017 в 01:36
45

Если вы часто используете большое количество исключений, вы можете заранее определить кортеж, чтобы вам не приходилось повторно вводить их много раз.

#This example code is a technique I use in a library that connects with websites to gather data

ConnectErrs  = (URLError, SSLError, SocketTimeoutError, BadStatusLine, ConnectionResetError)

def connect(url, data):
    #do connection and return some data
    return(received_data)

def some_function(var_a, var_b, ...):
    try: o = connect(url, data)
    except ConnectErrs as e:
        #do the recovery stuff
    blah #do normal stuff you would do if no exception occurred

ПРИМЕЧАНИЯ:

  1. Если вам также нужно перехватывать другие исключения, кроме тех, что указаны в предварительно определенный кортеж, вам нужно будет определить другой блок except.

  2. Если вы просто не можете терпеть глобальную переменную, определите ее в main () и передайте его туда, где необходимо ...

avatar
M.Usman
17 августа 2017 в 11:56
25

Один из способов сделать это ...

try:
   You do your operations here;
   ......................
except(Exception1[, Exception2[,...ExceptionN]]]):
   If there is any exception from the given exception list, 
   then execute this block.
   ......................
else:
   If there is no exception then execute this block. 

, а другой способ - создать метод, который выполняет задачу, выполняемую блоком except, и вызывать его через весь блок except, который вы пишете.

try:
   You do your operations here;
   ......................
except Exception1:
    functionname(parameterList)
except Exception2:
    functionname(parameterList)
except Exception3:
    functionname(parameterList)
else:
   If there is no exception then execute this block. 

def functionname( parameters ):
   //your task..
   return [expression]

Я знаю, что второй способ - не лучший способ сделать это, но я просто показываю несколько способов сделать это.

chizou
2 июля 2019 в 03:11
1

Я использую второе, потому что у меня есть два разных исключения, каждое из которых нужно обрабатывать по-разному. Что-то не так?

Eponymous
13 августа 2019 в 19:29
2

@majikman Второй метод с несколькими предложениями, каждое из которых вызывает одну и ту же функцию, не лучший вариант, когда вы пытаетесь не повторяться и делаете одно и то же для двух исключений. (См. Другие ответы, чтобы узнать, как это правильно сделать). Однако наличие нескольких предложений except является нормальным, если вы хотите обрабатывать исключения по-другому.

avatar
fedorqui 'SO stop harming'
30 октября 2014 в 10:01
58

Из документации Python -> 8.3 Обработка исключений:

Оператор try может иметь более одного предложения except, чтобы указать обработчики для разных исключений. Максимум один обработчик будет выполнен. Обработчики обрабатывают только исключения, возникающие в соответствующее предложение try, а не в других обработчиках той же попытки утверждение. Предложение except может называть несколько исключений как заключенный в скобки кортеж, например:

except (RuntimeError, TypeError, NameError):
    pass

Обратите внимание, что скобки вокруг этого кортежа обязательны, потому что кроме ValueError, e: был синтаксис, используемый для того, что обычно записывается как except ValueError as e: в современном Python (описанном ниже). Старый синтаксис по-прежнему поддерживается для обратной совместимости. Это означает, что except RuntimeError, TypeError не эквивалентен except (RuntimeError, TypeError): но до except RuntimeError as TypeError: а это не то, что вам нужно.

avatar
Aaron Hall
21 июня 2014 в 04:20
393

Как перехватить несколько исключений в одной строке (кроме блока)

Сделайте это:

try:
    may_raise_specific_errors():
except (SpecificErrorOne, SpecificErrorTwo) as error:
    handle(error) # might log or have some other default behavior...

Скобки необходимы из-за устаревшего синтаксиса, в котором запятые использовались для присвоения имени объекта ошибки. Ключевое слово as используется для назначения. Вы можете использовать любое имя для объекта ошибки, я предпочитаю error лично.

Передовой опыт

Чтобы сделать это способом, который в настоящее время совместим с Python, вам необходимо разделить исключения запятыми и заключить их в круглые скобки, чтобы отличаться от более раннего синтаксиса, который назначал экземпляр исключения для имени переменной, следуя типу исключения, который должен быть пойман с запятой.

Вот пример простого использования:

import sys

try:
    mainstuff()
except (KeyboardInterrupt, EOFError): # the parens are necessary
    sys.exit(0)

Я указываю только эти исключения, чтобы не скрывать ошибки, при обнаружении которых я ожидаю полную трассировку стека.

Это задокументировано здесь: https://docs.python.org/tutorial/errors.html

Вы можете назначить исключение переменной (e является обычным явлением, но вы можете предпочесть более подробную переменную, если у вас длинная обработка исключений или ваша среда IDE выделяет только более крупные выборки, как у меня). имеет атрибут args. Вот пример:

import sys

try:
    mainstuff()
except (KeyboardInterrupt, EOFError) as err: 
    print(err)
    print(err.args)
    sys.exit(0)

Обратите внимание, что в Python 3 объект err выпадает из области видимости при завершении блока except.

Устарело

Вы можете увидеть код, в котором ошибка записывается через запятую. Это использование, единственная форма, доступная в Python 2.5 и ранее, устарело, и если вы хотите, чтобы ваш код был совместим с продвижением в Python 3, вам следует обновить синтаксис, чтобы использовать новую форму:

import sys

try:
    mainstuff()
except (KeyboardInterrupt, EOFError), err: # don't do this in Python 2.6+
    print err
    print err.args
    sys.exit(0)

Если вы видите назначение имени запятой в своей кодовой базе и используете Python 2.5 или выше, переключитесь на новый способ выполнения этого, чтобы ваш код оставался совместимым при обновлении.

suppress менеджер контекста

Принятый ответ на самом деле состоит из 4 строк кода, минимум:

try:
    do_something()
except (IDontLikeYouException, YouAreBeingMeanException) as e:
    pass

Строки try, except, pass могут обрабатываться в одной строке с помощью диспетчера подавления контекста, доступного в Python 3.4:

from contextlib import suppress

with suppress(IDontLikeYouException, YouAreBeingMeanException):
     do_something()

Поэтому, если вы хотите pass для определенных исключений, используйте suppress.

Mache
17 декабря 2019 в 09:14
17

Хорошее добавление suppress, гораздо более читаемое, чем просто выполнение pass на except