О ловле ЛЮБОГО исключения

698

Как я могу написать try/ exceptблок, который перехватывает все исключения?

user469652
источник
4
В большинстве случаев вы, вероятно, делаете что-то неправильно, если пытаетесь поймать какое-либо исключение. Я имею в виду, что вы можете просто что-то неправильно написать в своем коде, и вы даже не будете знать об этом. Рекомендуется ловить конкретные исключения.
vwvolodya
12
Чтобы быть более точным, перехват всех возможных исключений является проблемой, только если они перехвачены молча. Трудно придумать, где еще подходит этот подход, кроме того, где распечатанные сообщения об ошибках печатаются sys.stderrи, возможно, регистрируются. Это вполне допустимое и распространенное исключение.
Евгений Сергеев
ты пробовал try: whatever() except Exception as e: exp_capture() :?
Чарли Паркер

Ответы:

564

Вы можете, но, вероятно, не должны:

try:
    do_something()
except:
    print "Caught it!"

Тем не менее, это также будет ловить исключения, как, KeyboardInterruptи вы обычно не хотите этого, не так ли? Если вы повторно не вызвали исключение сразу - посмотрите следующий пример из документации :

try:
    f = open('myfile.txt')
    s = f.readline()
    i = int(s.strip())
except IOError as (errno, strerror):
    print "I/O error({0}): {1}".format(errno, strerror)
except ValueError:
    print "Could not convert data to an integer."
except:
    print "Unexpected error:", sys.exc_info()[0]
    raise
Тим Питцкер
источник
30
Возможное решение: effbot.org/zone/stupid-exceptions-keyboardinterrupt.htm
Микель,
15
Ваше последнее утверждение неверно, вам нужно явно сказать, except Exception:что «голое», за исключением того, что у вас есть, также поймает BaseException.
Пиклер
7
Вы действительно должны печатать в stderr.
nyuszika7h
41
Я очень, очень сильно не согласен с утверждением «не должен». Вы должны делать это экономно. Бывают случаи, когда вы имеете дело со сторонними библиотеками (иногда динамически загружаемыми !!), которые полностью сходят с ума из-за исключений, и отслеживание их всех может быть очень болезненной задачей, и если вы пропустите только одну, у вас будет очень очень огромная болезненная ошибка в вашей системе. При этом хорошо бы выследить как можно больше и правильно их обработать, а затем создать резервную копию всех, что вы пропустили.
Blaze
26
Что я нахожу также странным, так это то, что в языке утиной типизации, где вы не объявляете переменные экземпляра, он внезапно очень беспокоится о том, чтобы не печатать все ваши исключения. Хм!
Blaze
839

Помимо except:простого предложения (которое, как говорили другие, не следует использовать), вы можете просто уловить Exception:

import traceback
import logging

try:
    whatever()
except Exception as e:
    logging.error(traceback.format_exc())
    # Logs the error appropriately. 

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

Преимущество except Exceptionнад голым exceptсостоит в том, что есть несколько исключений, которые он не поймает, наиболее очевидно KeyboardInterruptи SystemExit: если вы поймали и проглотили их, вы могли бы затруднить кому-либо выход из сценария.

Дункан
источник
У меня в голове было то же самое, но это их недостаток, предположим, что это две ошибки, когда однажды перехвачена и, за исключением того, что вы просто печатаете, вы выйдете из блока try и никогда не узнаете вторую ошибку. .
6
Для всех, кто интересуется, полностью вопреки моим ожиданиям, он все равно будет ловить подклассы без исключения, такие как int, по крайней мере, в python 2.x.
Джозеф Гарвин
5
@JosephGarvin, это неверно, то есть это не будет ловить «не исключения», которые не подкласс Exception. Обратите внимание, что невозможно вызвать intисключение, и при попытке сделать это возникает TypeErrorисключение, которое except Exceptionв таком случае будет включено вмещающее предложение. С другой стороны, класс старого стиля может быть поднят и квалифицируется как «не-исключение» , который не подкласс Exception- это будет пойман на голом exceptпункт , но не с помощью except Exceptionпункта.
Йоэль
4
@JosephGarvin проверьте эту запись в блоге: chris-lamb.co.uk/posts/no-one-expected-string-literal-exception Я с @Yoel на этом, ваше тестирование только что замаскировалоTypeError
Дункан
2
@CharlieParker ничего плохого в том, чтобы поймать их, если это то, что вы хотите, но в основном это не так. Вызов sys.exit()обычно означает, что вы ожидаете, что приложение завершит работу, но если вы поймаете SystemExit, оно не будет. Аналогично, если вы нажмете control-C на работающем скрипте (Ctrl-break на окнах), вы ожидаете, что программа остановится, чтобы не перехватить ошибку и продолжить работу. Но вы можете поймать любой / оба из них, если вы хотите сделать очистку перед существующим.
Дункан
100

Вы можете сделать это для обработки общих исключений

try:
    a = 2/0
except Exception as e:
    print e.__doc__
    print e.message
vwvolodya
источник
8
Это может не охватить все исключения, так как базовым классом для всех исключений является BaseException, и я столкнулся с рабочим кодом, который не входит в семейство классов Exception. См. Docs.python.org/3/library/… для подробностей об этом.
DDay
4
Это не охватывает все исключения.
Andy_A̷n̷d̷y̷
6
Технически, он должен перехватывать все несистемные выходы. Из документа @DDay связано: « исключение BaseException: базовый класс для всех встроенных исключений. Он не предназначен для непосредственного наследования пользовательскими классами (для этого используйте Exception)». Если вы не работаете с кодом, который игнорирует это, или вам нужно перехватывать системные исключения, вышеприведенное должно быть в порядке.
Питер Кассетта
@PeterCassetta, когда захочется поймать систему, выходящую из исключения? Кажется, общая нить в вопросе, что мы не хотим их ловить, но я не понимаю, почему. Почему обычно нет?
Чарли Паркер
68

Чтобы поймать все возможные исключения, поймать BaseException . Это на вершине иерархии исключений:

Python 3: https://docs.python.org/3.5/library/exceptions.html#exception-hierarchy

Python 2.7: https://docs.python.org/2.7/library/exceptions.html#exception-hierarchy

try:
    something()
except BaseException as error:
    print('An exception occurred: {}'.format(error))

Но, как упоминали другие люди, это обычно не требуется, только для особых случаев.

gitaarik
источник
1
Желает ли сохранить прогресс выполнения длительной работы после нажатия Ctrl-C так необычно?
BallpointBen
54

Очень простой пример, похожий на найденный здесь:

http://docs.python.org/tutorial/errors.html#defining-clean-up-actions

Если вы пытаетесь перехватить ВСЕ исключения, поместите весь свой код в оператор «try:» вместо «print» Выполнение действия, которое может вызвать исключение. ».

try:
    print "Performing an action which may throw an exception."
except Exception, error:
    print "An exception was thrown!"
    print str(error)
else:
    print "Everything looks great!"
finally:
    print "Finally is called directly after executing the try statement whether an exception is thrown or not."

В приведенном выше примере вы увидите вывод в следующем порядке:

1) Выполнение действия, которое может вызвать исключение.

2) И, наконец, вызывается непосредственно после выполнения оператора try независимо от того, было ли выброшено исключение.

3) «Исключение было брошено!» или "Все выглядит отлично!" в зависимости от того, было ли выброшено исключение.

Надеюсь это поможет!

Джошуа Бернс
источник
26

Есть несколько способов сделать это, в частности, с Python 3.0 и выше

Подход 1

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

def bad_method():
    try:
        sqrt = 0**-1
    except Exception as e:
        print(e)

bad_method()

Подход 2

Этот подход рекомендуется, потому что он предоставляет более подробную информацию о каждом исключении. Это включает в себя:

  • Номер строки для вашего кода
  • Имя файла
  • Фактическая ошибка более многословно

Единственным недостатком является необходимость импорта tracback.

import traceback

def bad_method():
    try:
        sqrt = 0**-1
    except Exception:
        print(traceback.print_exc())

bad_method()
grepit
источник
21

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

try:
    raise IndexError #as test error
except Exception as e:
    excepName = type(e).__name__ # returns the name of the exception
Данило
источник
2
try:
    whatever()
except:
    # this will catch any exception or error

Стоит отметить, что это неправильное кодирование Python. Это также поймает много ошибок, которые вы можете не захотеть поймать.

Ювал Адам
источник
просто используйте, за исключением того, что не кэшируйте все исключения, упомянутые в некоторых других ответах. Вы должны использовать BaseException для этой цели, но, как вы сказали, никто не должен перехватывать все исключения, подобные этой. Я думаю, для начала нормально, если цель состоит в том, чтобы добавить больше деталей, кроме как во время разработки, но я не думаю, что это будет ...
Pyglouthon