Uh oh!
There was an error while loading. Please reload this page.
Add and document py::error_already_set::discard_as_unraisable() - #2372
Conversation
jbarlow83
commented
Aug 9, 2020
Added a missing documentation file I edited and forgot to include, and fixed Python 2.7 support. I believe the current CI errors are due to recent changes in the CMake setup. |
YannickJadoul
left a comment
There was a problem hiding this comment.
Nice addition :-) Thanks for taking the time to work on this, @jbarlow83!
I personally don't need this in my project, I believe, so I don't have problems with keeping this a very thin/minor PR (mostly in the docs), but I'm wondering why we're not including the other ideas (e.g., the lambda-wrapping utility function)?
| of type :class:`error_already_set`. If this error is thrown out of a class destructor, | ||
| ``std::terminate()`` will be called, terminating the process. Class destructors | ||
| must catch all exceptions of type :class:`error_already_set` to discard the Python | ||
| exception using :meth:`error_already_set::discard_as_unraisable`. (In addition, |
There was a problem hiding this comment.
Minor thing: I don't think the parentheses are needed here. This is important enough to realize :-)
Another minor thing: Maybe mention things like py::cast_error, etc, that are also C++ errors and not caught by py::error_already_set?
Major thing: reading this, I wonder "what do you do then, for C++ excecptions? Maybe we should still provide a wrapper function such that users can do this without calling the C API?
There was a problem hiding this comment.
Do you mean std::terminate() -> std::terminate?
I think classes.rst needs a bigger overhaul than this but was trying to limit the scope of changes for now. In particular, py::error_already_set serves a different function from the C++ exception wrappers, and needs to be separately explained separately from them and then an example added that brings the two concepts together. In particular, I find it pretty unintuitive that if you have a Python -> C++ -> Python callback situation, and you throw ValueError from Python, you can't catch py::value_error. You can only catch py::value_error when another C++ function throws it.
I think we could add py::builtin_exception::discard_as_unraisable. It's a little trickier to convert a std::exception into a Python exception, because I don't think we should invoke the exception translator as part of dealing with an unraisable exception.
There was a problem hiding this comment.
Do you mean
std::terminate()->std::terminate?
No, sorry, I meant the parentheses around "In addition, ...".
I think classes.rst needs a bigger overhaul than this but was trying to limit the scope of changes for now. In particular,
py::error_already_setserves a different function from the C++ exception wrappers, and needs to be separately explained separately from them and then an example added that brings the two concepts together.We could add
py::builtin_exception::discard_as_unraisable. It's a little trickier to convert astd::exceptioninto a Python exception, because I don't think we should invoke the exception translator as part of dealing with an unraisable exception.
Alright, yes, I can see. In that case, this is definitely better than what we had, so more changes can come later! :-)
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
ac4a891 to
9ca68caCompareThere was a problem hiding this comment.
Right. If this is ready, I'll happily press "merge"!
EDIT: Oh, wait. First CI needs to be fixed. But I'm guessing that's linked to #2381?
05ca399 to
5437330Comparejbarlow83
commented
Aug 11, 2020
@YannickJadoul CI is fixed |
YannickJadoul
commented
Aug 11, 2020
@jbarlow83 Great! So, ready? Let's maybe still get a quick review from a few others. @bstaletic, @henryiii, @rwgk, and/or @EricCousineau-TRI, anything to add/change? |
jbarlow83
commented
Aug 12, 2020
Yes, should be ready |
jbarlow83
commented
Aug 12, 2020
rwgk
left a comment
There was a problem hiding this comment.
Thanks, looks great to me. Just a couple minor suggestions.
| PyErr_WriteUnraisable(err_context.ptr()); | ||
| } | ||
| void discard_as_unraisable(const char *err_context) { | ||
| auto obj = reinterpret_steal<object>(PYBIND11_FROM_STRING(err_context)); |
There was a problem hiding this comment.
discard_as_unraisable(reinterpret_steal<object>(PYBIND11_FROM_STRING(err_context)));
?
to avoid code duplication.
There was a problem hiding this comment.
Sounds good. BTW reason for not calling str here is that it is defined before str is.
There was a problem hiding this comment.
Hmmm, guess there's no way to forward declare that?
I suppose it's not worth the effort to try rearranging things :-/
| assert triggered[0] is True | ||
| captured = capsys.readouterr() | ||
| captured_err = captured[1] # Python 3.5 doesn't like .err the namedtuple |
There was a problem hiding this comment.
# captured.err does not work with Python 3.5
?
There was a problem hiding this comment.
The captured object is a namedtuple or similar object with a namedtuple-like interface.
We'd want to say captured.err here, but that failed in CI on Python 3.5 on Debian and nowhere else. Perhaps it's specific to a particular minor revision. I'll fix the typo.
| if hooked: | ||
| assert triggered[0] is True | ||
| captured_err = capsys.readouterr()[1] # Returns (stdout, syserr) |
There was a problem hiding this comment.
typo? Should this be stderr?
If you fix that I'll merge this PR, we have 4 approvals already.
There was a problem hiding this comment.
FWIW If capsys.readouterr() always returns that tuple, then consider doing tuple unpacking:
_, captures_err = capsys.readouterr()
To deal with exceptions that hit destructors or other noexcept functions. Includes fixes to support Python 2.7 and extends documentation on error handling. @virtuald and @YannickJadoul both contributed to this PR.
rwgk
commented
Aug 16, 2020
Hi @jbarlow83, thanks for the contribution! I'll merge this now. |
To deal with exceptions that hit destructors or other noexcept functions.
Supercedes #2358
@virtuald@YannickJadoul