1Exceptions 2########## 3 4Built-in C++ to Python exception translation 5============================================ 6 7When Python calls C++ code through pybind11, pybind11 provides a C++ exception handler 8that will trap C++ exceptions, translate them to the corresponding Python exception, 9and raise them so that Python code can handle them. 10 11pybind11 defines translations for ``std::exception`` and its standard 12subclasses, and several special exception classes that translate to specific 13Python exceptions. Note that these are not actually Python exceptions, so they 14cannot be examined using the Python C API. Instead, they are pure C++ objects 15that pybind11 will translate the corresponding Python exception when they arrive 16at its exception handler. 17 18.. tabularcolumns:: |p{0.5\textwidth}|p{0.45\textwidth}| 19 20+--------------------------------------+--------------------------------------+ 21| Exception thrown by C++ | Translated to Python exception type | 22+======================================+======================================+ 23| :class:`std::exception` | ``RuntimeError`` | 24+--------------------------------------+--------------------------------------+ 25| :class:`std::bad_alloc` | ``MemoryError`` | 26+--------------------------------------+--------------------------------------+ 27| :class:`std::domain_error` | ``ValueError`` | 28+--------------------------------------+--------------------------------------+ 29| :class:`std::invalid_argument` | ``ValueError`` | 30+--------------------------------------+--------------------------------------+ 31| :class:`std::length_error` | ``ValueError`` | 32+--------------------------------------+--------------------------------------+ 33| :class:`std::out_of_range` | ``IndexError`` | 34+--------------------------------------+--------------------------------------+ 35| :class:`std::range_error` | ``ValueError`` | 36+--------------------------------------+--------------------------------------+ 37| :class:`std::overflow_error` | ``OverflowError`` | 38+--------------------------------------+--------------------------------------+ 39| :class:`pybind11::stop_iteration` | ``StopIteration`` (used to implement | 40| | custom iterators) | 41+--------------------------------------+--------------------------------------+ 42| :class:`pybind11::index_error` | ``IndexError`` (used to indicate out | 43| | of bounds access in ``__getitem__``, | 44| | ``__setitem__``, etc.) | 45+--------------------------------------+--------------------------------------+ 46| :class:`pybind11::key_error` | ``KeyError`` (used to indicate out | 47| | of bounds access in ``__getitem__``, | 48| | ``__setitem__`` in dict-like | 49| | objects, etc.) | 50+--------------------------------------+--------------------------------------+ 51| :class:`pybind11::value_error` | ``ValueError`` (used to indicate | 52| | wrong value passed in | 53| | ``container.remove(...)``) | 54+--------------------------------------+--------------------------------------+ 55| :class:`pybind11::type_error` | ``TypeError`` | 56+--------------------------------------+--------------------------------------+ 57| :class:`pybind11::buffer_error` | ``BufferError`` | 58+--------------------------------------+--------------------------------------+ 59| :class:`pybind11::import_error` | ``import_error`` | 60+--------------------------------------+--------------------------------------+ 61| Any other exception | ``RuntimeError`` | 62+--------------------------------------+--------------------------------------+ 63 64Exception translation is not bidirectional. That is, *catching* the C++ 65exceptions defined above above will not trap exceptions that originate from 66Python. For that, catch :class:`pybind11::error_already_set`. See :ref:`below 67<handling_python_exceptions_cpp>` for further details. 68 69There is also a special exception :class:`cast_error` that is thrown by 70:func:`handle::call` when the input arguments cannot be converted to Python 71objects. 72 73Registering custom translators 74============================== 75 76If the default exception conversion policy described above is insufficient, 77pybind11 also provides support for registering custom exception translators. 78To register a simple exception conversion that translates a C++ exception into 79a new Python exception using the C++ exception's ``what()`` method, a helper 80function is available: 81 82.. code-block:: cpp 83 84 py::register_exception<CppExp>(module, "PyExp"); 85 86This call creates a Python exception class with the name ``PyExp`` in the given 87module and automatically converts any encountered exceptions of type ``CppExp`` 88into Python exceptions of type ``PyExp``. 89 90It is possible to specify base class for the exception using the third 91parameter, a `handle`: 92 93.. code-block:: cpp 94 95 py::register_exception<CppExp>(module, "PyExp", PyExc_RuntimeError); 96 97Then `PyExp` can be caught both as `PyExp` and `RuntimeError`. 98 99The class objects of the built-in Python exceptions are listed in the Python 100documentation on `Standard Exceptions <https://docs.python.org/3/c-api/exceptions.html#standard-exceptions>`_. 101The default base class is `PyExc_Exception`. 102 103When more advanced exception translation is needed, the function 104``py::register_exception_translator(translator)`` can be used to register 105functions that can translate arbitrary exception types (and which may include 106additional logic to do so). The function takes a stateless callable (e.g. a 107function pointer or a lambda function without captured variables) with the call 108signature ``void(std::exception_ptr)``. 109 110When a C++ exception is thrown, the registered exception translators are tried 111in reverse order of registration (i.e. the last registered translator gets the 112first shot at handling the exception). 113 114Inside the translator, ``std::rethrow_exception`` should be used within 115a try block to re-throw the exception. One or more catch clauses to catch 116the appropriate exceptions should then be used with each clause using 117``PyErr_SetString`` to set a Python exception or ``ex(string)`` to set 118the python exception to a custom exception type (see below). 119 120To declare a custom Python exception type, declare a ``py::exception`` variable 121and use this in the associated exception translator (note: it is often useful 122to make this a static declaration when using it inside a lambda expression 123without requiring capturing). 124 125The following example demonstrates this for a hypothetical exception classes 126``MyCustomException`` and ``OtherException``: the first is translated to a 127custom python exception ``MyCustomError``, while the second is translated to a 128standard python RuntimeError: 129 130.. code-block:: cpp 131 132 static py::exception<MyCustomException> exc(m, "MyCustomError"); 133 py::register_exception_translator([](std::exception_ptr p) { 134 try { 135 if (p) std::rethrow_exception(p); 136 } catch (const MyCustomException &e) { 137 exc(e.what()); 138 } catch (const OtherException &e) { 139 PyErr_SetString(PyExc_RuntimeError, e.what()); 140 } 141 }); 142 143Multiple exceptions can be handled by a single translator, as shown in the 144example above. If the exception is not caught by the current translator, the 145previously registered one gets a chance. 146 147If none of the registered exception translators is able to handle the 148exception, it is handled by the default converter as described in the previous 149section. 150 151.. seealso:: 152 153 The file :file:`tests/test_exceptions.cpp` contains examples 154 of various custom exception translators and custom exception types. 155 156.. note:: 157 158 Call either ``PyErr_SetString`` or a custom exception's call 159 operator (``exc(string)``) for every exception caught in a custom exception 160 translator. Failure to do so will cause Python to crash with ``SystemError: 161 error return without exception set``. 162 163 Exceptions that you do not plan to handle should simply not be caught, or 164 may be explicitly (re-)thrown to delegate it to the other, 165 previously-declared existing exception translators. 166 167.. _handling_python_exceptions_cpp: 168 169Handling exceptions from Python in C++ 170====================================== 171 172When C++ calls Python functions, such as in a callback function or when 173manipulating Python objects, and Python raises an ``Exception``, pybind11 174converts the Python exception into a C++ exception of type 175:class:`pybind11::error_already_set` whose payload contains a C++ string textual 176summary and the actual Python exception. ``error_already_set`` is used to 177propagate Python exception back to Python (or possibly, handle them in C++). 178 179.. tabularcolumns:: |p{0.5\textwidth}|p{0.45\textwidth}| 180 181+--------------------------------------+--------------------------------------+ 182| Exception raised in Python | Thrown as C++ exception type | 183+======================================+======================================+ 184| Any Python ``Exception`` | :class:`pybind11::error_already_set` | 185+--------------------------------------+--------------------------------------+ 186 187For example: 188 189.. code-block:: cpp 190 191 try { 192 // open("missing.txt", "r") 193 auto file = py::module_::import("io").attr("open")("missing.txt", "r"); 194 auto text = file.attr("read")(); 195 file.attr("close")(); 196 } catch (py::error_already_set &e) { 197 if (e.matches(PyExc_FileNotFoundError)) { 198 py::print("missing.txt not found"); 199 } else if (e.matches(PyExc_PermissionError)) { 200 py::print("missing.txt found but not accessible"); 201 } else { 202 throw; 203 } 204 } 205 206Note that C++ to Python exception translation does not apply here, since that is 207a method for translating C++ exceptions to Python, not vice versa. The error raised 208from Python is always ``error_already_set``. 209 210This example illustrates this behavior: 211 212.. code-block:: cpp 213 214 try { 215 py::eval("raise ValueError('The Ring')"); 216 } catch (py::value_error &boromir) { 217 // Boromir never gets the ring 218 assert(false); 219 } catch (py::error_already_set &frodo) { 220 // Frodo gets the ring 221 py::print("I will take the ring"); 222 } 223 224 try { 225 // py::value_error is a request for pybind11 to raise a Python exception 226 throw py::value_error("The ball"); 227 } catch (py::error_already_set &cat) { 228 // cat won't catch the ball since 229 // py::value_error is not a Python exception 230 assert(false); 231 } catch (py::value_error &dog) { 232 // dog will catch the ball 233 py::print("Run Spot run"); 234 throw; // Throw it again (pybind11 will raise ValueError) 235 } 236 237Handling errors from the Python C API 238===================================== 239 240Where possible, use :ref:`pybind11 wrappers <wrappers>` instead of calling 241the Python C API directly. When calling the Python C API directly, in 242addition to manually managing reference counts, one must follow the pybind11 243error protocol, which is outlined here. 244 245After calling the Python C API, if Python returns an error, 246``throw py::error_already_set();``, which allows pybind11 to deal with the 247exception and pass it back to the Python interpreter. This includes calls to 248the error setting functions such as ``PyErr_SetString``. 249 250.. code-block:: cpp 251 252 PyErr_SetString(PyExc_TypeError, "C API type error demo"); 253 throw py::error_already_set(); 254 255 // But it would be easier to simply... 256 throw py::type_error("pybind11 wrapper type error"); 257 258Alternately, to ignore the error, call `PyErr_Clear 259<https://docs.python.org/3/c-api/exceptions.html#c.PyErr_Clear>`_. 260 261Any Python error must be thrown or cleared, or Python/pybind11 will be left in 262an invalid state. 263 264.. _unraisable_exceptions: 265 266Handling unraisable exceptions 267============================== 268 269If a Python function invoked from a C++ destructor or any function marked 270``noexcept(true)`` (collectively, "noexcept functions") throws an exception, there 271is no way to propagate the exception, as such functions may not throw. 272Should they throw or fail to catch any exceptions in their call graph, 273the C++ runtime calls ``std::terminate()`` to abort immediately. 274 275Similarly, Python exceptions raised in a class's ``__del__`` method do not 276propagate, but are logged by Python as an unraisable error. In Python 3.8+, a 277`system hook is triggered 278<https://docs.python.org/3/library/sys.html#sys.unraisablehook>`_ 279and an auditing event is logged. 280 281Any noexcept function should have a try-catch block that traps 282class:`error_already_set` (or any other exception that can occur). Note that 283pybind11 wrappers around Python exceptions such as 284:class:`pybind11::value_error` are *not* Python exceptions; they are C++ 285exceptions that pybind11 catches and converts to Python exceptions. Noexcept 286functions cannot propagate these exceptions either. A useful approach is to 287convert them to Python exceptions and then ``discard_as_unraisable`` as shown 288below. 289 290.. code-block:: cpp 291 292 void nonthrowing_func() noexcept(true) { 293 try { 294 // ... 295 } catch (py::error_already_set &eas) { 296 // Discard the Python error using Python APIs, using the C++ magic 297 // variable __func__. Python already knows the type and value and of the 298 // exception object. 299 eas.discard_as_unraisable(__func__); 300 } catch (const std::exception &e) { 301 // Log and discard C++ exceptions. 302 third_party::log(e); 303 } 304 } 305 306.. versionadded:: 2.6 307