sys.exc_info()
- получает информации об исключении;sys.exception()
- возвращает экземпляр исключения;sys.excepthook()
- обработка необработанных исключений;sys.unraisablehook()
обработка невыполнимых исключений;sys.excepthook
и sys.exc_info
.sys.exc_info()
:Функция sys.exc_info()
возвращает кортеж из трех значений, которые предоставляют информацию об исключении, которое в данный момент обрабатывается. Возвращаемая информация относится как к текущему потоку, так и к текущему кадру стека. Если текущий кадр стека не обрабатывает исключение, информация берется из вызывающего кадра стека или его вызывающего и т. д. до тех пор, пока не будет найден кадр стека, который обрабатывает исключение. Здесь "обработка исключения" определяется как "выполнение условия исключения". Для любого стекового фрейма доступна только информация об исключении, которое обрабатывается в данный момент.
Если нигде в стеке исключение не обрабатывается, возвращается кортеж, содержащий три значения None
. В противном случае возвращаются значения (type, value, traceback)
.
Их значение:
type
получает тип обрабатываемого исключения;value
получает экземпляр исключения;traceback
получает объект traceback
.Изменено в Python 3.11: type
и traceback
поля теперь являются производными от value
(экземпляр исключения), поэтому, когда исключение модифицируется во время его обработки, изменения отражаются в результатах последующих вызовов sys.exc_info()
.
Пояснения к изменению в Python 3.11. Эта функция возвращает представление обработанного исключения в старом стиле (как описано выше). Если в настоящее время обрабатывается исключение
e
(поэтомуsys.exception()
(добавлена в Python 3.11) возвращаетe
),sys.exc_info()
возвращает кортеж(type(e), e, e.__traceback__)
. То есть кортеж, содержащий тип исключения (подклассBaseException
), само исключение и объект трассировки, который обычно инкапсулирует стек вызовов в точке, где в последний раз возникло исключение.
sys.exception()
:Функция sys.exception()
(добавлена в Python 3.11), вызываемая во время выполнения обработчика исключений (например, предложения except
или except*
), возвращает экземпляр исключения, который был перехвачен этим обработчиком. Когда обработчики исключений вложены друг в друга, то доступно только исключение, обработанное самым внутренним обработчиком.
Если обработчик исключений не выполняется, эта функция возвращает None
.
Новое в Python 3.11.
sys.excepthook(type, value, traceback)
:Функция sys.excepthook()
выводит заданную трассировку и исключение в sys.stderr
.
Когда возникает исключение и не обрабатывается, то интерпретатор вызывает sys.excepthook()
с тремя аргументами: классом исключения type
, экземпляром исключения value
и объектом трассировки traceback
. В интерактивном сеансе это происходит непосредственно перед тем, как управление возвращается к приглашению ввода. В программе Python это происходит непосредственно перед выходом из программы. Обработка исключений верхнего уровня может быть настроена путем назначения другой функции с тремя аргументами для sys.excepthook
.
Вызывает событие аудита sys.excepthook
с аргументами hook
, type
, value
, traceback
. Если хук/ловушка не была установлена, то аргумент hook
может быть None
.
Если какой-либо хук вызывает исключение от RuntimeError
и его производных, то вызов хука/ловушки будет подавлен. В противном случае исключение перехвата будет отмечено как невыполненное и будет вызван sys.excepthook()
.
Смотрим пример:
import sys def my_excepthook(type, value, traceback): print('Unhandled error:', type, value) sys.excepthook = my_excepthook print('Before exception') raise RuntimeError('This is the error message') print('After exception') # Before exception # Unhandled error: <class 'RuntimeError'> This is the error message
Так как блока try/except
нет вокруг строки, в которой возбуждается исключение, то последний вызов print()
не выполняется, хотя хук/ловушка для исключения установлена.
sys.unraisablehook(unraisable, /)
:Функция sys.unraisablehook()
(добавлена в Python 3.8) обрабатывает невыполнимое исключение.
Вызывается, когда возникает исключение, но Python не может его обработать. Например, когда вызывает исключение деструктор или во время сборки мусора.
Аргумент unraisable
имеет следующие атрибуты:
exc_type
: Тип исключения.exc_value
: значение исключения, может быть None.exc_traceback
: Отслеживание исключения, может быть Нет.err_msg
: Сообщение об ошибке, может быть Нет.object
: Объект, вызвавший исключение, может быть None.По этот хук форматирует err_msg
и object
как: f '{err_msg}: {object! R}'
. Используйте сообщение об ошибке "Exception ignored in", если err_msg
- Нет.
Функцией sys.unraisablehook()
можно переопределить поведение невыполнимых исключений.
Сохранение exc_value
с использованием пользовательского хука может создать ссылочный цикл. Его следует явно очистить, чтобы прервать ссылочный цикл, когда исключение больше не требуется.
Сохранение object
с помощью настраиваемого хука может воскресить его, если он установлен на объект, который завершается. Избегайте сохранения объекта object
после завершения кастомного хука, чтобы избежать воскрешения объектов.
Смотрите также функцию sys.excepthook()
, которая обрабатывает неперехваченные исключения.
Вызывает событие аудита sys.unraisablehook
с аргументами hook
, unraisable
, когда происходит исключение, которое не может быть обработано. Объект unraisable
- это то же самое, что и то, что будет передано хуку. Если хук не был установлен, то аргумент hook
может быть None
.
Новое в Python 3.8.
sys.excepthook
и sys.exc_info
.sys.exc_info()
для вывода сообщения об ошибке;Ctrl+C
;sys.exc_info()
для вывода сообщения об ошибке.В представленном коде ниже, последняя инструкция except
может опустить имя исключения. Используйте такую конструкцию с крайней осторожностью, таким образом можно легко замаскировать реальную ошибку! Здесь можно использовать sys.exc_info()
для вывода сообщения об ошибке, а затем повторно вызвать исключение, что позволяет вызывающей стороне также обработать исключение:
import sys try: f = open('myfile.txt') s = f.readline() i = int(s.strip()) except OSError as err: print("OS error: {0}".format(err)) except ValueError: print("Не удалось преобразовать данные в целое число.") except: print("Непредвиденная ошибка:", sys.exc_info()[0]) raise
Есть моменты, когда предпочтителен явный обработчик исключений, либо для ясности кода, либо во избежание конфликтов с библиотеками, которые пытаются установить свои собственные sys.excepthook
. В этих случаях может быть создана общая функция-обработчик, которой не нужно явно передавать объект исключения, вызывая exc_info()
для извлечения текущего исключения для потока.
import sys import threading import time def with_exception(): exc_type, exc_value = sys.exc_info()[:2] print(f'{exc_type.__name__} => {exc_value} in {threading.current_thread().name}') def cause_exception(delay): time.sleep(delay) raise RuntimeError('Error message') def thread_target(delay): try: cause_exception(delay) except RuntimeError: with_exception() threads = [ threading.Thread(target=thread_target, args=(0.3,)), threading.Thread(target=thread_target, args=(0.1,)), ] for t in threads: t.start() for t in threads: t.join() # RuntimeError => Error message in Thread-2 # RuntimeError => Error message in Thread-1
В этом примере избегается введение циклической ссылки между объектом трассировки и локальной переменной в текущем кадре, игнорируя эту часть возвращаемого значения из sys.exc_info()
. Если требуется трассировка, например чтобы ее можно было зарегистрировать явным образом удалите локальную переменную используя del, чтобы избежать циклов.
Ctrl+C
.Пример перехвата исключения KeyboardInterrupt
, которое возникает, когда пользователь нажимает клавишу прерывания программы, обычно это Ctrl+C или Delete.
Например, если запустить код, представленный ниже, то по нажатию Ctrl+C можно увидеть трассировку исключения KeyboardInterrupt
.
>>> import time >>> while True: ... time.sleep(5) ... # ^CTraceback (most recent call last): # File "<stdin>", line 2, in <module> # KeyboardInterrupt
А что делать, если не нужна трассировка, если программу прервал пользователь? Эти сведения пользователю не о чем не скажут, а в некоторых случаях могут испугать. Напишем функцию перехвата этого исключения, в которой вместо ошибок будем выводить "Программа завершена по нажатию CTRL+C".
>>> import time, sys # функция перехвата исключения 'KeyboardInterrupt' >>> def my_except_hook(exctype, value, traceback): ... if exctype == KeyboardInterrupt: ... print("Программа завершена по нажатию CTRL+C") ... else: ... sys.__excepthook__(exctype, value, traceback) ... # применим функцию перехвата `my_except_hook` >>> sys.excepthook = my_except_hook >>> while True: ... time.sleep(5) ... # ^CПрограмма завершена по нажатию CTRL+C
Теперь по нажатию Ctrl+C выводится "Программа завершена по нажатию CTRL+C"