blob: 75ad7f7f4a527a93a41eb0785e2beb8419208014 [file] [log] [blame]
Dean Moldovan67b52d82016-10-16 19:12:43 +02001Exceptions
2##########
3
4Built-in exception translation
5==============================
6
7When C++ code invoked from Python throws an ``std::exception``, it is
8automatically converted into a Python ``Exception``. pybind11 defines multiple
9special exception classes that will map to different types of Python
10exceptions:
11
12.. tabularcolumns:: |p{0.5\textwidth}|p{0.45\textwidth}|
13
Antony Lee8fbb5592018-03-11 16:15:56 -070014+--------------------------------------+--------------------------------------+
15| C++ exception type | Python exception type |
16+======================================+======================================+
17| :class:`std::exception` | ``RuntimeError`` |
18+--------------------------------------+--------------------------------------+
19| :class:`std::bad_alloc` | ``MemoryError`` |
20+--------------------------------------+--------------------------------------+
21| :class:`std::domain_error` | ``ValueError`` |
22+--------------------------------------+--------------------------------------+
23| :class:`std::invalid_argument` | ``ValueError`` |
24+--------------------------------------+--------------------------------------+
25| :class:`std::length_error` | ``ValueError`` |
26+--------------------------------------+--------------------------------------+
Wenzel Jakob51ca6b02019-06-11 22:47:37 +020027| :class:`std::out_of_range` | ``IndexError`` |
Antony Lee8fbb5592018-03-11 16:15:56 -070028+--------------------------------------+--------------------------------------+
29| :class:`std::range_error` | ``ValueError`` |
30+--------------------------------------+--------------------------------------+
Francesco Biscanideb3cb22019-11-14 08:56:58 +010031| :class:`std::overflow_error` | ``OverflowError`` |
32+--------------------------------------+--------------------------------------+
Antony Lee8fbb5592018-03-11 16:15:56 -070033| :class:`pybind11::stop_iteration` | ``StopIteration`` (used to implement |
34| | custom iterators) |
35+--------------------------------------+--------------------------------------+
36| :class:`pybind11::index_error` | ``IndexError`` (used to indicate out |
37| | of bounds access in ``__getitem__``, |
38| | ``__setitem__``, etc.) |
39+--------------------------------------+--------------------------------------+
40| :class:`pybind11::value_error` | ``ValueError`` (used to indicate |
41| | wrong value passed in |
42| | ``container.remove(...)``) |
43+--------------------------------------+--------------------------------------+
44| :class:`pybind11::key_error` | ``KeyError`` (used to indicate out |
45| | of bounds access in ``__getitem__``, |
46| | ``__setitem__`` in dict-like |
47| | objects, etc.) |
48+--------------------------------------+--------------------------------------+
49| :class:`pybind11::error_already_set` | Indicates that the Python exception |
50| | flag has already been set via Python |
51| | API calls from C++ code; this C++ |
52| | exception is used to propagate such |
53| | a Python exception back to Python. |
54+--------------------------------------+--------------------------------------+
Dean Moldovan67b52d82016-10-16 19:12:43 +020055
56When a Python function invoked from C++ throws an exception, it is converted
57into a C++ exception of type :class:`error_already_set` whose string payload
58contains a textual summary.
59
60There is also a special exception :class:`cast_error` that is thrown by
61:func:`handle::call` when the input arguments cannot be converted to Python
62objects.
63
64Registering custom translators
65==============================
66
67If the default exception conversion policy described above is insufficient,
68pybind11 also provides support for registering custom exception translators.
69To register a simple exception conversion that translates a C++ exception into
70a new Python exception using the C++ exception's ``what()`` method, a helper
71function is available:
72
73.. code-block:: cpp
74
75 py::register_exception<CppExp>(module, "PyExp");
76
77This call creates a Python exception class with the name ``PyExp`` in the given
78module and automatically converts any encountered exceptions of type ``CppExp``
79into Python exceptions of type ``PyExp``.
80
81When more advanced exception translation is needed, the function
82``py::register_exception_translator(translator)`` can be used to register
83functions that can translate arbitrary exception types (and which may include
84additional logic to do so). The function takes a stateless callable (e.g. a
85function pointer or a lambda function without captured variables) with the call
86signature ``void(std::exception_ptr)``.
87
88When a C++ exception is thrown, the registered exception translators are tried
89in reverse order of registration (i.e. the last registered translator gets the
90first shot at handling the exception).
91
92Inside the translator, ``std::rethrow_exception`` should be used within
93a try block to re-throw the exception. One or more catch clauses to catch
94the appropriate exceptions should then be used with each clause using
95``PyErr_SetString`` to set a Python exception or ``ex(string)`` to set
96the python exception to a custom exception type (see below).
97
98To declare a custom Python exception type, declare a ``py::exception`` variable
99and use this in the associated exception translator (note: it is often useful
100to make this a static declaration when using it inside a lambda expression
101without requiring capturing).
102
103
104The following example demonstrates this for a hypothetical exception classes
105``MyCustomException`` and ``OtherException``: the first is translated to a
106custom python exception ``MyCustomError``, while the second is translated to a
107standard python RuntimeError:
108
109.. code-block:: cpp
110
111 static py::exception<MyCustomException> exc(m, "MyCustomError");
112 py::register_exception_translator([](std::exception_ptr p) {
113 try {
114 if (p) std::rethrow_exception(p);
115 } catch (const MyCustomException &e) {
116 exc(e.what());
117 } catch (const OtherException &e) {
118 PyErr_SetString(PyExc_RuntimeError, e.what());
119 }
120 });
121
122Multiple exceptions can be handled by a single translator, as shown in the
123example above. If the exception is not caught by the current translator, the
124previously registered one gets a chance.
125
126If none of the registered exception translators is able to handle the
127exception, it is handled by the default converter as described in the previous
128section.
129
130.. seealso::
131
132 The file :file:`tests/test_exceptions.cpp` contains examples
133 of various custom exception translators and custom exception types.
134
135.. note::
136
137 You must call either ``PyErr_SetString`` or a custom exception's call
138 operator (``exc(string)``) for every exception caught in a custom exception
139 translator. Failure to do so will cause Python to crash with ``SystemError:
140 error return without exception set``.
141
142 Exceptions that you do not plan to handle should simply not be caught, or
luz.paz28cb6762018-01-09 12:30:19 -0500143 may be explicitly (re-)thrown to delegate it to the other,
Dean Moldovan67b52d82016-10-16 19:12:43 +0200144 previously-declared existing exception translators.