Содержание страницы
Обработка исключений¶Exception Handling
Функции, описанные в этой главе, позволяют обрабатывать и возбуждать исключения Python. Важно понимать некоторые основы обработки исключений в Python. Механизм отчасти напоминает переменную errno в Unix: существует глобальный индикатор (по потоку) последней произошедшей ошибки. Большинство функций не сбрасывают его при успехе, но устанавливают, указывая причину ошибки при неудаче. Также большинство функций возвращают индикатор ошибки, обычно NULL, если они должны возвращать указатель, или -1, если возвращают целое число (исключение: функции PyArg_* возвращают 1 при успехе и 0 при неудаче).
Когда функция должна завершиться ошибкой, потому что вызванная ей функция завершилась ошибкой, она обычно не устанавливает индикатор ошибки; его уже установила вызванная функция. Она отвечает либо за обработку ошибки и очистку исключения, либо за возврат после освобождения всех удерживаемых ресурсов (таких как ссылки на объекты или выделенная память); она не должна продолжать нормальное выполнение, если не готова обработать ошибку. При возврате из-за ошибки важно указать вызывающему коду, что ошибка была установлена. Если ошибка не обрабатывается или не аккуратно распространяется, последующие вызовы Python/C API могут вести себя не так, как задумано, и могут отказать загадочным образом.
Индикатор ошибки состоит из трёх объектов Python, соответствующих результату вызова sys.exc_info(). Существуют функции API для взаимодействия с индикатором ошибки разными способами. Для каждого потока предусмотрен отдельный индикатор ошибки.
- void PyErr_Print()¶
- Выводит стандартную трассировку в sys.stderr и очищает индикатор ошибки. Вызывайте эту функцию только при установленном индикаторе ошибки (иначе возникнет фатальная ошибка!).
- PyObject* PyErr_Occurred()¶
- Возвращаемое значение: заимствованная ссылка.
Проверяет, установлен ли индикатор ошибки. Если установлен, возвращает тип исключения (первый аргумент последнего вызова одной из функций PyErr_Set* или PyErr_Restore). Если не установлен, возвращает NULL. Возвращаемое значение не находится в вашем владении, поэтому не нужно вызывать Py_DECREF для него.
Примечание
Не сравнивайте возвращаемое значение с конкретным исключением; вместо этого используйте PyErr_ExceptionMatches, показанную ниже. (Сравнение может легко оказаться неверным, поскольку исключение может быть экземпляром, а не классом, в случае классового исключения, или может быть подклассом ожидаемого исключения.)
- int PyErr_ExceptionMatches(PyObject *exc)¶
- Эквивалентно PyErr_GivenExceptionMatches(PyErr_Occurred(), exc). Функцию следует вызывать только тогда, когда исключение действительно установлено; в противном случае возникнет нарушение доступа к памяти.
- int PyErr_GivenExceptionMatches(PyObject *given, PyObject *exc)¶
- Возвращает истину, если исключение given соответствует исключению в exc. Если exc – объект класса, также возвращает истину, когда given является экземпляром подкласса. Если exc – кортеж, выполняется поиск совпадения по всем исключениям кортежа (и рекурсивно по вложенным кортежам).
- void PyErr_NormalizeException(PyObject**exc, PyObject**val, PyObject**tb)¶
- При определенных обстоятельствах значения, возвращаемые PyErr_Fetch (см. ниже), могут быть «ненормализованными», то есть *exc является объектом класса, а *val не является экземпляром того же класса. Эта функция может использоваться для создания экземпляра класса в таком случае. Если значения уже нормализованы, ничего не происходит. Отложенная нормализация реализована для повышения производительности.
- void PyErr_Clear()¶
- Очищает индикатор ошибки. Если индикатор ошибки не установлен, эффекта нет.
- void PyErr_Fetch(PyObject **ptype, PyObject **pvalue, PyObject **ptraceback)¶
Извлекает индикатор ошибки в три переменные, адреса которых передаются. Если индикатор ошибки не установлен, устанавливает все три переменные в NULL. Если установлен, он будет очищен, и вы получаете владение ссылкой на каждый извлечённый объект. Значение и объект traceback могут быть NULL, даже если объект типа не NULL.
Примечание
Эта функция обычно используется только кодом, которому нужно обрабатывать исключения, или кодом, которому требуется временно сохранить и восстановить индикатор ошибки.
- void PyErr_Restore(PyObject *type, PyObject *value, PyObject *traceback)¶
Set the error indicator from the three objects. If the error indicator is already set, it is cleared first. If the objects are NULL, the error indicator is cleared. Do not pass a NULL type and non-NULL value or traceback. The exception type should be a class. Do not pass an invalid exception type or value. (Violating these rules will cause subtle problems later.) This call takes away a reference to each object: you must own a reference to each object before the call and after the call you no longer own these references. (If you don’t understand this, don’t use this function. I warned you.)
Примечание
Эта функция обычно используется только кодом, которому нужно временно сохранить и восстановить индикатор ошибки; используйте PyErr_Fetch для сохранения текущего состояния исключения.
- void PyErr_SetString(PyObject *type, const char *message)¶
- Это наиболее распространённый способ установки индикатора ошибки. Первый аргумент задаёт тип исключения; обычно это одно из стандартных исключений, например PyExc_RuntimeError. Увеличивать его счётчик ссылок не требуется. Второй аргумент – сообщение об ошибке; оно преобразуется в строковый объект.
- void PyErr_SetObject(PyObject *type, PyObject *value)¶
- Эта функция похожа на PyErr_SetString, но позволяет указать произвольный объект Python в качестве «значения» исключения.
- PyObject* PyErr_Format(PyObject *exception, const char *format, ...)¶
- Возвращаемое значение: всегда NULL.
Эта функция устанавливает индикатор ошибки и возвращает NULL. Параметр exception должен быть исключением Python (классом, а не экземпляром). Параметр format должен быть строкой, содержащей коды формата, аналогично printf. Часть width.precision перед кодом формата разбирается, но часть ширины игнорируется.
Символы формата Тип Описание %% н/д Буквальный символ %. %c int Одиночный символ, представленный как C int. %d int Полностью эквивалентно printf("%d"). %u беззнаковый int Полностью эквивалентно printf("%u"). %ld long Полностью эквивалентно printf("%ld"). %lu беззнаковый long Полностью эквивалентно printf("%lu"). %zd Py_ssize_t Полностью эквивалентно printf("%zd"). %zu size_t Полностью эквивалентно printf("%zu"). %i int Полностью эквивалентно printf("%i"). %x int Полностью эквивалентно printf("%x"). %s char* Нуль-терминированный массив символов C. %p void* Шестнадцатеричное представление указателя C. В основном эквивалентно printf("%p") за исключением того, что гарантированно начинается с литерала 0x независимо от того, что выдает printf на данной платформе. Нераспознанный символ формата приводит к тому, что вся оставшаяся строка формата копируется как есть в результирующую строку, а все лишние аргументы отбрасываются.
- int PyErr_BadArgument()¶
- Это сокращённая запись для PyErr_SetString(PyExc_TypeError, message), где message указывает, что встроенная операция была вызвана с недопустимым аргументом. В основном используется внутри.
- PyObject* PyErr_NoMemory()¶
- Возвращаемое значение: всегда NULL.
Это сокращённая запись для PyErr_SetNone(PyExc_MemoryError); она возвращает NULL, чтобы функция выделения объекта могла написать return PyErr_NoMemory(); при нехватке памяти.
- PyObject* PyErr_SetFromErrno(PyObject *type)¶
- Возвращаемое значение: всегда NULL.
Это удобная функция для возбуждения исключения, когда библиотечная функция C вернула ошибку и установила переменную C errno. Она создаёт объект кортежа, первый элемент которого – целочисленное значение errno, а второй – соответствующее сообщение об ошибке (полученное из strerror), а затем вызывает PyErr_SetObject(type, object). В Unix, когда значение errno равно EINTR, что указывает на прерванный системный вызов, эта функция вызывает PyErr_CheckSignals, и если та установила индикатор ошибки, оставляет его установленным. Функция всегда возвращает NULL, поэтому функция-обёртка вокруг системного вызова может написать return PyErr_SetFromErrno(type);, когда системный вызов возвращает ошибку.
- PyObject* PyErr_SetFromErrnoWithFilename(PyObject *type, const char *filename)¶
- Возвращаемое значение: всегда NULL.
Аналогична PyErr_SetFromErrno, с дополнительным поведением: если filename не равен NULL, он передаётся конструктору type в качестве третьего параметра. В случае таких исключений, как IOError и OSError, это используется для определения атрибута filename экземпляра исключения.
- PyObject* PyErr_SetFromWindowsErr(int ierr)¶
- Возвращаемое значение: всегда NULL.
Это удобная функция для возбуждения WindowsError. Если вызвана с ierr равным 0, используется код ошибки, возвращённый вызовом GetLastError. Она вызывает функцию Win32 FormatMessage для получения Windows-описания кода ошибки, заданного ierr или GetLastError, затем создаёт объект кортежа, первый элемент которого – значение ierr, а второй – соответствующее сообщение об ошибке (полученное из FormatMessage), и затем вызывает PyErr_SetObject(PyExc_WindowsError, object). Эта функция всегда возвращает NULL. Доступность: Windows.
- PyObject* PyErr_SetExcFromWindowsErr(PyObject *type, int ierr)¶
- Возвращаемое значение: всегда NULL.
Аналогична PyErr_SetFromWindowsErr, с дополнительным параметром, указывающим тип возбуждаемого исключения. Доступность: Windows.
- PyObject* PyErr_SetFromWindowsErrWithFilename(int ierr, const char *filename)¶
- Возвращаемое значение: всегда NULL.
Аналогична PyErr_SetFromWindowsErr, с дополнительным поведением: если filename не равен NULL, он передаётся конструктору WindowsError в качестве третьего параметра. Доступность: Windows.
- PyObject* PyErr_SetExcFromWindowsErrWithFilename(PyObject *type, int ierr, char *filename)¶
- Возвращаемое значение: всегда NULL.
Аналогична PyErr_SetFromWindowsErrWithFilename, с дополнительным параметром, указывающим тип возбуждаемого исключения. Доступность: Windows.
- void PyErr_BadInternalCall()¶
- Это сокращённая форма для PyErr_SetString(PyExc_SystemError, message), где message указывает, что внутренняя операция (например, функция Python/C API) была вызвана с недопустимым аргументом. В основном используется внутри.
- int PyErr_WarnEx(PyObject *category, char *message, int stacklevel)¶
Выдаёт предупреждение. Аргумент category – это категория предупреждения (см. ниже) или NULL; аргумент message – строка сообщения. stacklevel – это положительное число, задающее количество стековых фреймов; предупреждение будет выдано из текущей исполняемой строки кода в этом стековом фрейме. Значение stacklevel равное 1 означает функцию, вызывающую PyErr_WarnEx, 2 – функцию выше неё, и так далее.
Эта функция обычно выводит предупреждение в sys.stderr; однако пользователь может указать, что предупреждения должны превращаться в ошибки, и в этом случае она возбуждает исключение. Также возможно, что функция возбуждает исключение из-за проблемы в механизме предупреждений (реализация импортирует модуль warnings для выполнения основной работы). Возвращаемое значение – 0, если исключение не возбуждено, или -1, если исключение возбуждено. (Нельзя определить, было ли сообщение предупреждения на самом деле напечатано, а также причину исключения; это сделано намеренно.) Если возбуждено исключение, вызывающий код должен выполнить обычную обработку исключения (например, Py_DECREF принадлежащие ссылки и вернуть значение ошибки).
Категории предупреждений должны быть подклассами Warning; категория предупреждения по умолчанию – RuntimeWarning. Стандартные категории предупреждений Python доступны как глобальные переменные, имена которых – PyExc_, за которым следует имя исключения Python. Они имеют тип PyObject*; все они являются объектами классов. Их имена: PyExc_Warning, PyExc_UserWarning, PyExc_UnicodeWarning, PyExc_DeprecationWarning, PyExc_SyntaxWarning, PyExc_RuntimeWarning и PyExc_FutureWarning. PyExc_Warning является подклассом PyExc_Exception; остальные категории предупреждений являются подклассами PyExc_Warning.
Информацию об управлении предупреждениями см. в документации модуля warnings и опции -W в документации командной строки. C API для управления предупреждениями не существует.
- int PyErr_WarnExplicit(PyObject *category, const char *message, const char *filename, int lineno, const char *module, PyObject *registry)¶
- Выдаёт предупреждение с явным контролем всех атрибутов предупреждения. Это простая обёртка вокруг функции Python warnings.warn_explicit(), см. описание там. Аргументы module и registry могут быть установлены в NULL для получения эффекта по умолчанию, как описано там.
- int PyErr_CheckSignals()¶
Эта функция взаимодействует с обработкой сигналов Python. Она проверяет, был ли отправлен сигнал процессам, и если да, вызывает соответствующий обработчик сигнала. Если модуль signal поддерживается, может быть вызван обработчик сигнала, написанный на Python. Во всех случаях действие по умолчанию для SIGINT – возбуждение исключения KeyboardInterrupt. Если исключение возбуждено, устанавливается индикатор ошибки, и функция возвращает -1; в противном случае функция возвращает 0. Индикатор ошибки может быть сброшен или не сброшен, если он был установлен ранее.
- void PyErr_SetInterrupt()¶
Эта функция имитирует поступление сигнала SIGINT – при следующем вызове PyErr_CheckSignals будет возбуждено KeyboardInterrupt. Функцию можно вызывать, не удерживая блокировку интерпретатора.
- int PySignal_SetWakeupFd(int fd)¶
- Эта вспомогательная функция задаёт файловый дескриптор, в который будет записан байт '\0' при получении сигнала. Возвращает предыдущий такой файловый дескриптор. Значение -1 отключает эту возможность; это начальное состояние. Эквивалентно signal.set_wakeup_fd() в Python, но без проверки ошибок. fd должен быть корректным файловым дескриптором. Функцию следует вызывать только из главного потока.
- PyObject* PyErr_NewException(char *name, PyObject *base, PyObject *dict)¶
- Возвращаемое значение: новая ссылка.
Эта вспомогательная функция создаёт и возвращает новый объект исключения. Аргумент name должен задавать имя нового исключения – строку C в формате module.class. Аргументы base и dict обычно равны NULL. Функция создаёт объект класса, производного от Exception (на C доступен как PyExc_Exception).
Атрибут __module__ нового класса устанавливается в первую часть (до последней точки) аргумента name, а имя класса – в последнюю часть (после последней точки). Аргумент base можно использовать для указания альтернативных базовых классов; это может быть как один класс, так и кортеж классов. Аргумент dict можно использовать для указания словаря переменных и методов класса.
- void PyErr_WriteUnraisable(PyObject *obj)¶
Эта вспомогательная функция выводит предупреждение в sys.stderr, когда исключение установлено, но интерпретатор не может его фактически возбудить. Используется, например, когда исключение возникает в методе __del__().
Функция вызывается с одним аргументом obj, который идентифицирует контекст, в котором возникло не вызываемое исключение. В сообщении предупреждения будет выведено repr от obj.
Стандартные исключения¶Standard Exceptions
Все стандартные исключения Python доступны как глобальные переменные, имена которых состоят из PyExc_, за которым следует имя исключения Python. Они имеют тип PyObject*; все они являются объектами классов. Для полноты картины, вот все переменные:
| Имя в C | Имя в Python | Примечания |
|---|---|---|
| PyExc_BaseException | BaseException | (1) |
| PyExc_Exception | исключение | (1) |
| PyExc_ArithmeticError | ArithmeticError | (1) |
| PyExc_LookupError | LookupError | (1) |
| PyExc_AssertionError | AssertionError | |
| PyExc_AttributeError | AttributeError | |
| PyExc_EOFError | EOFError | |
| PyExc_EnvironmentError | EnvironmentError | (1) |
| PyExc_FloatingPointError | FloatingPointError | |
| PyExc_IOError | IOError | |
| PyExc_ImportError | ImportError | |
| PyExc_IndexError | IndexError | |
| PyExc_KeyError | KeyError | |
| PyExc_KeyboardInterrupt | KeyboardInterrupt | |
| PyExc_MemoryError | MemoryError | |
| PyExc_NameError | NameError | |
| PyExc_NotImplementedError | NotImplementedError | |
| PyExc_OSError | OSError | |
| PyExc_OverflowError | OverflowError | |
| PyExc_ReferenceError | ReferenceError | (2) |
| PyExc_RuntimeError | RuntimeError | |
| PyExc_SyntaxError | SyntaxError | |
| PyExc_SystemError | SystemError | |
| PyExc_SystemExit | SystemExit | |
| PyExc_TypeError | TypeError | |
| PyExc_ValueError | ValueError | |
| PyExc_WindowsError | WindowsError | (3) |
| PyExc_ZeroDivisionError | ZeroDivisionError |
Примечания:
- Это базовый класс для других стандартных исключений.
- То же самое, что weakref.ReferenceError.
- Определён только в Windows; код, использующий это, должен проверять, определён ли макрос препроцессора MS_WINDOWS.