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