Source

python-clinic / Doc / c-api / exceptions.rst

Full commit

Exception Handling

The functions described in this chapter will let you handle and raise Python exceptions. It is important to understand some of the basics of Python exception handling. It works somewhat like the Unix :c:data:`errno` variable: there is a global indicator (per thread) of the last error that occurred. Most functions don't clear this on success, but will set it to indicate the cause of the error on failure. Most functions also return an error indicator, usually NULL if they are supposed to return a pointer, or -1 if they return an integer (exception: the :c:func:`PyArg_\*` functions return 1 for success and 0 for failure).

When a function must fail because some function it called failed, it generally doesn't set the error indicator; the function it called already set it. It is responsible for either handling the error and clearing the exception or returning after cleaning up any resources it holds (such as object references or memory allocations); it should not continue normally if it is not prepared to handle the error. If returning due to an error, it is important to indicate to the caller that an error has been set. If the error is not handled or carefully propagated, additional calls into the Python/C API may not behave as intended and may fail in mysterious ways.

The error indicator consists of three Python objects corresponding to the result of sys.exc_info(). API functions exist to interact with the error indicator in various ways. There is a separate error indicator for each thread.

Exception Objects

Unicode Exception Objects

The following functions are used to create and modify Unicode exceptions from C.

Recursion Control

These two functions provide a way to perform safe recursive calls at the C level, both in the core and in extension modules. They are needed if the recursive code does not necessarily invoke Python code (which tracks its recursion depth automatically).

Properly implementing :c:member:`~PyTypeObject.tp_repr` for container types requires special recursion handling. In addition to protecting the stack, :c:member:`~PyTypeObject.tp_repr` also needs to track objects to prevent cycles. The following two functions facilitate this functionality. Effectively, these are the C equivalent to :func:`reprlib.recursive_repr`.

Standard Exceptions

All standard Python exceptions are available as global variables whose names are PyExc_ followed by the Python exception name. These have the type :c:type:`PyObject\*`; they are all class objects. For completeness, here are all the variables:

C Name Python Name Notes
:c:data:`PyExc_BaseException` :exc:`BaseException` (1)
:c:data:`PyExc_Exception` :exc:`Exception` (1)
:c:data:`PyExc_ArithmeticError` :exc:`ArithmeticError` (1)
:c:data:`PyExc_LookupError` :exc:`LookupError` (1)
:c:data:`PyExc_AssertionError` :exc:`AssertionError`  
:c:data:`PyExc_AttributeError` :exc:`AttributeError`  
:c:data:`PyExc_BlockingIOError` :exc:`BlockingIOError`  
:c:data:`PyExc_BrokenPipeError` :exc:`BrokenPipeError`  
:c:data:`PyExc_ChildProcessError` :exc:`ChildProcessError`  
:c:data:`PyExc_ConnectionError` :exc:`ConnectionError`  
:c:data:`PyExc_ConnectionAbortedError` :exc:`ConnectionAbortedError`  
:c:data:`PyExc_ConnectionRefusedError` :exc:`ConnectionRefusedError`  
:c:data:`PyExc_ConnectionResetError` :exc:`ConnectionResetError`  
:c:data:`PyExc_FileExistsError` :exc:`FileExistsError`  
:c:data:`PyExc_FileNotFoundError` :exc:`FileNotFoundError`  
:c:data:`PyExc_EOFError` :exc:`EOFError`  
:c:data:`PyExc_FloatingPointError` :exc:`FloatingPointError`  
:c:data:`PyExc_ImportError` :exc:`ImportError`  
:c:data:`PyExc_IndexError` :exc:`IndexError`  
:c:data:`PyExc_InterruptedError` :exc:`InterruptedError`  
:c:data:`PyExc_IsADirectoryError` :exc:`IsADirectoryError`  
:c:data:`PyExc_KeyError` :exc:`KeyError`  
:c:data:`PyExc_KeyboardInterrupt` :exc:`KeyboardInterrupt`  
:c:data:`PyExc_MemoryError` :exc:`MemoryError`  
:c:data:`PyExc_NameError` :exc:`NameError`  
:c:data:`PyExc_NotADirectoryError` :exc:`NotADirectoryError`  
:c:data:`PyExc_NotImplementedError` :exc:`NotImplementedError`  
:c:data:`PyExc_OSError` :exc:`OSError` (1)
:c:data:`PyExc_OverflowError` :exc:`OverflowError`  
:c:data:`PyExc_PermissionError` :exc:`PermissionError`  
:c:data:`PyExc_ProcessLookupError` :exc:`ProcessLookupError`  
:c:data:`PyExc_ReferenceError` :exc:`ReferenceError` (2)
:c:data:`PyExc_RuntimeError` :exc:`RuntimeError`  
:c:data:`PyExc_SyntaxError` :exc:`SyntaxError`  
:c:data:`PyExc_SystemError` :exc:`SystemError`  
:c:data:`PyExc_TimeoutError` :exc:`TimeoutError`  
:c:data:`PyExc_SystemExit` :exc:`SystemExit`  
:c:data:`PyExc_TypeError` :exc:`TypeError`  
:c:data:`PyExc_ValueError` :exc:`ValueError`  
:c:data:`PyExc_ZeroDivisionError` :exc:`ZeroDivisionError`  

These are compatibility aliases to :c:data:`PyExc_OSError`:

C Name Notes
:c:data:`PyExc_EnvironmentError`  
:c:data:`PyExc_IOError`  
:c:data:`PyExc_WindowsError` (3)

Notes:

  1. This is a base class for other standard exceptions.
  2. This is the same as :exc:`weakref.ReferenceError`.
  3. Only defined on Windows; protect code that uses this by testing that the preprocessor macro MS_WINDOWS is defined.