Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6039db8

Browse files
committed
Issue #18776: atexit callbacks now display their full traceback when they raise an exception.
2 parents fbc3c3c + 24201d4 commit 6039db8

3 files changed

Lines changed: 32 additions & 0 deletions

File tree

Lib/test/test_atexit.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,25 @@ def test_raise_unnormalized(self):
7777
self.assertRaises(ZeroDivisionError, atexit._run_exitfuncs)
7878
self.assertIn("ZeroDivisionError", self.stream.getvalue())
7979

80+
def test_print_tracebacks(self):
81+
# Issue #18776: the tracebacks should be printed when errors occur.
82+
def f():
83+
1/0 # one
84+
def g():
85+
1/0 # two
86+
def h():
87+
1/0 # three
88+
atexit.register(f)
89+
atexit.register(g)
90+
atexit.register(h)
91+
92+
self.assertRaises(ZeroDivisionError, atexit._run_exitfuncs)
93+
stderr = self.stream.getvalue()
94+
self.assertEqual(stderr.count("ZeroDivisionError"), 3)
95+
self.assertIn("# one", stderr)
96+
self.assertIn("# two", stderr)
97+
self.assertIn("# three", stderr)
98+
8099
def test_stress(self):
81100
a = [0]
82101
def inc():

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ Core and Builtins
4242
Library
4343
-------
4444

45+
- Issue #18776: atexit callbacks now display their full traceback when they
46+
raise an exception.
47+
4548
- Issue #17827: Add the missing documentation for ``codecs.encode`` and
4649
``codecs.decode``.
4750

Python/pythonrun.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1919,6 +1919,16 @@ PyErr_Display(PyObject *exception, PyObject *value, PyObject *tb)
19191919
{
19201920
PyObject *seen;
19211921
PyObject *f = PySys_GetObject("stderr");
1922+
if (PyExceptionInstance_Check(value)
1923+
&& tb != NULL && PyTraceBack_Check(tb)) {
1924+
/* Put the traceback on the exception, otherwise it won't get
1925+
displayed. See issue #18776. */
1926+
PyObject *cur_tb = PyException_GetTraceback(value);
1927+
if (cur_tb == NULL)
1928+
PyException_SetTraceback(value, tb);
1929+
else
1930+
Py_DECREF(cur_tb);
1931+
}
19221932
if (f == Py_None) {
19231933
/* pass */
19241934
}

0 commit comments

Comments
 (0)