Как перехватить несколько исключений в одной строке? (в блоке "except")
Я знаю, что могу сделать:
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
Итак, мои попытки перехватить два разных исключения точно не увенчались успехом.
Есть ли способ сделать это?
Переведено автоматически
Ответ 1
Предложение except может называть несколько исключений в виде кортежа, заключенного в скобки, например
except (IDontLikeYouException, YouAreBeingMeanException) as e:
pass
Или только для Python 2:
except (IDontLikeYouException, YouAreBeingMeanException), e:
pass
Разделение исключения от переменной запятой по-прежнему будет работать в Python 2.6 и 2.7, но теперь устарело и не работает в Python 3; теперь вы должны использовать as
.
Ответ 2
Как мне перехватить несколько исключений в одной строке (кроме блока)
Сделайте это:
try:
may_raise_specific_errors():
except (SpecificErrorOne, SpecificErrorTwo) as error:
handle(error) # might log or have some other default behavior...
Скобки требуются из-за более старого синтаксиса, в котором для присвоения имени объекту error использовались запятые. Для присвоения используется ключевое слово as
. Вы можете использовать любое имя для объекта error, мне больше нравится 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
.
Ответ 3
Из документации по Python -> 8.3 Обработка исключений:
Оператор
try
может содержать более одного предложения except, чтобы указать обработчики для разных исключений. Будет выполнен не более одного обработчика. Обработчики обрабатывают только исключения, возникающие в соответствующем предложении try, а не в других обработчиках того же оператора try . Предложение except может называть несколько исключений в виде кортежа, заключенного в скобки, например:
except (RuntimeError, TypeError, NameError):
passОбратите внимание, что круглые скобки вокруг этого кортежа обязательны, потому что
exceptValueError, e:
был синтаксисом, используемым для того, что обычно
записывается какexcept ValueError as e:
в современном Python (описано
ниже). Старый синтаксис по-прежнему поддерживается для обратной совместимости.
Это означает, чтоexcept RuntimeError, TypeError
не эквивалентно
except (RuntimeError, TypeError):
ноexcept RuntimeError as
TypeError:
что не то, что вы хотите.
Ответ 4
Если вы часто используете большое количество исключений, вы можете заранее определить кортеж, поэтому вам не придется повторно вводить их много раз.
#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
Примечания:
Если вам также нужно перехватить другие исключения, отличные от тех, что содержатся в заранее определенном кортеже, вам нужно будет определить другой блок except .
Если вы просто не можете терпеть глобальную переменную, определите ее в main() и передавайте везде, где это необходимо...