Ловіть кілька винятків в одному рядку (крім блоку)


2755

Я знаю, що можу:

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

Отже, мої зусилля, щоб зловити два чіткі винятки, точно не випливають.

Чи є спосіб це зробити?


6
Зауважте, що в Python 3 останній більше не є синтаксисом.
Герріт

Відповіді:


3722

З документації Python :

За винятком пункту, наприклад, можна назвати декілька винятків як кортеж, що вбивається в дужках

except (IDontLikeYouException, YouAreBeingMeanException) as e:
    pass

Або лише для Python 2:

except (IDontLikeYouException, YouAreBeingMeanException), e:
    pass

Виділення винятку зі змінної комою все ще працюватиме в Python 2.6 та 2.7, але тепер застаріле і не працює в Python 3; тепер ви повинні використовувати as.


9
Я спробував це ... з list, і це призвело до TypeError. Схоже, помилки повинні бути в тому, що потрібно tupleловитись на роботу, як очікувалося.
BallpointBen

4
Чому б ви коли-небудь користувались списком, коли чітко бачите, що документально підтверджено, що в цьому випадку потрібен кортеж?
механічне_

6
Незрозуміло, чи є "скоплений в дужках" просто синтаксичний чи потрібен добросовісний кортеж. "Parenthesized" вводить в оману, оскільки ви можете створити кортеж без дужок в іншому місці, а потім використовувати його в exceptрядку. Це обов'язково лише в дужках, якщо вони створені в exceptрядку.
BallpointBen

5
@JosephBani, що з виразами генератора?
jammertheprogrammer

12
@JosephBani Це зовсім не так. В 2 + (x * 2), (x * 2)звичайно, не кортеж. Дужки - це загальна групувальна конструкція. Визначальною характеристикою кортежу є те, що він містить кому - див . Документацію на Python : "Зауважте, що саме кома робить кортеж, а не круглі дужки."
Soren Bjornstad

314

Як зафіксувати кілька винятків в одному рядку (крім блоку)

Зробити це:

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 або новішої версії, перейдіть на новий спосіб зробити це, щоб ваш код залишався сумісним під час оновлення.

The 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.


2
Хороше доповнення suppress, багато більш читабельним , ніж просто робити passнаexcept
Маші

50

З документації Python -> 8.3 Обробка виключень :

У tryзаяві може бути більше одного, крім пункту, для вказівки обробників для різних винятків. Щонайбільше буде виконано один обробник. Обробники обробляють лише винятки, які трапляються у відповідному пробному пункті, а не в інших обробниках того самого оператора спробу. За винятком пункту, можна назвати кілька винятків як кортеж, вкладений у круглий круг, наприклад:

except (RuntimeError, TypeError, NameError):
    pass

Зауважте, що круглі дужки навколо цього кортежу обов'язкові, тому що крім ValueError, e:цього синтаксис використовувався для того, що зазвичай пишеться, як except ValueError as e:у сучасному Python (описано нижче). Старий синтаксис все ще підтримується для зворотної сумісності. Це означає except RuntimeError, TypeError, що не рівнозначно, except (RuntimeError, TypeError):але except RuntimeError as TypeError:якому не є те, що ви хочете.


35

Якщо ви часто використовуєте велику кількість винятків, ви можете заздалегідь визначити кортеж, тому вам не доведеться повторно вводити їх.

#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. Якщо вам також потрібно зафіксувати інші винятки, ніж ті, що є у попередньо визначеному кортежі, вам потрібно визначити інший, крім блоку.

  2. Якщо ви просто не можете допустити глобальну змінну, визначте її в main () та передайте її туди, де потрібно ...


17

Один із способів цього зробити ..

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]

Я знаю, що другий - це не найкращий спосіб зробити це, але я показую лише кілька способів зробити це.


Я використовую другий, оскільки у мене є два різних винятки, які потрібно обробляти по-різному. Чи щось не так у тому, щоб зробити це таким чином?
majikman

@majikman Другий метод з декількома пропозиціями, кожен із яких викликає одну і ту ж функцію, не найкращий, коли ви намагаєтесь не повторювати себе і робити те саме за два винятки. (Див. Інші відповіді, як правильно це зробити). Однак наявність декількох exceptпропозицій нормально, коли ви хочете по-різному обробляти винятки.
Однойменний
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.