diff options
| author | Peter Bierma <zintensitydev@gmail.com> | 2025-08-04 14:35:00 (GMT) |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-08-04 14:35:00 (GMT) |
| commit | e8251dc0ae6a85f6a0e427ae64fb0fe847eb3cf8 (patch) | |
| tree | 4b84339ca33cacefe3a80b24a97f5cbaf62bcf9d /Python/errors.c | |
| parent | 8943bb722f2f88a95ea6c5ee36bb5d540740d792 (diff) | |
| download | cpython-e8251dc0ae6a85f6a0e427ae64fb0fe847eb3cf8.zip cpython-e8251dc0ae6a85f6a0e427ae64fb0fe847eb3cf8.tar.gz cpython-e8251dc0ae6a85f6a0e427ae64fb0fe847eb3cf8.tar.bz2 | |
gh-134170: Add colorization to unraisable exceptions (#134183)
Default implementation of sys.unraisablehook() now uses traceback._print_exception_bltin() to print exceptions with colorized text.
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
Co-authored-by: Victor Stinner <vstinner@python.org>
Diffstat (limited to 'Python/errors.c')
| -rw-r--r-- | Python/errors.c | 27 |
1 files changed, 26 insertions, 1 deletions
diff --git a/Python/errors.c b/Python/errors.c index a3122f7..2688396 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -1444,12 +1444,16 @@ make_unraisable_hook_args(PyThreadState *tstate, PyObject *exc_type, It can be called to log the exception of a custom sys.unraisablehook. - Do nothing if sys.stderr attribute doesn't exist or is set to None. */ + This assumes 'file' is neither NULL nor None. + */ static int write_unraisable_exc_file(PyThreadState *tstate, PyObject *exc_type, PyObject *exc_value, PyObject *exc_tb, PyObject *err_msg, PyObject *obj, PyObject *file) { + assert(file != NULL); + assert(!Py_IsNone(file)); + if (obj != NULL && obj != Py_None) { if (err_msg != NULL && err_msg != Py_None) { if (PyFile_WriteObject(err_msg, file, Py_PRINT_RAW) < 0) { @@ -1484,6 +1488,27 @@ write_unraisable_exc_file(PyThreadState *tstate, PyObject *exc_type, } } + // Try printing the exception using the stdlib module. + // If this fails, then we have to use the C implementation. + PyObject *print_exception_fn = PyImport_ImportModuleAttrString("traceback", + "_print_exception_bltin"); + if (print_exception_fn != NULL && PyCallable_Check(print_exception_fn)) { + PyObject *args[2] = {exc_value, file}; + PyObject *result = PyObject_Vectorcall(print_exception_fn, args, 2, NULL); + int ok = (result != NULL); + Py_DECREF(print_exception_fn); + Py_XDECREF(result); + if (ok) { + // Nothing else to do + return 0; + } + } + else { + Py_XDECREF(print_exception_fn); + } + // traceback module failed, fall back to pure C + _PyErr_Clear(tstate); + if (exc_tb != NULL && exc_tb != Py_None) { if (PyTraceBack_Print(exc_tb, file) < 0) { /* continue even if writing the traceback failed */ |
