.. versionadded:: 3.8
+.. data:: __excepthook__
+
+ Holds the original value of :func:`threading.excepthook`. It is saved so that the
+ original value can be restored in case they happen to get replaced with
+ broken or alternative objects.
+
+ .. versionadded:: 3.10
.. function:: get_ident()
:func:`threading.setprofile` respectively.
(Contributed by Mario Corchero in :issue:`42251`.)
+Add :data:`threading.__excepthook__` to allow retrieving the original value
+of :func:`threading.excepthook` in case it is set to a broken or a different
+value.
+(Contributed by Mario Corchero in :issue:`42308`.)
+
traceback
---------
'Exception in threading.excepthook:\n')
self.assertEqual(err_str, 'threading_hook failed')
+ def test_original_excepthook(self):
+ def run_thread():
+ with support.captured_output("stderr") as output:
+ thread = ThreadRunFail(name="excepthook thread")
+ thread.start()
+ thread.join()
+ return output.getvalue()
+
+ def threading_hook(args):
+ print("Running a thread failed", file=sys.stderr)
+
+ default_output = run_thread()
+ with support.swap_attr(threading, 'excepthook', threading_hook):
+ custom_hook_output = run_thread()
+ threading.excepthook = threading.__excepthook__
+ recovered_output = run_thread()
+
+ self.assertEqual(default_output, recovered_output)
+ self.assertNotEqual(default_output, custom_hook_output)
+ self.assertEqual(custom_hook_output, "Running a thread failed\n")
+
class TimerTests(BaseTestCase):
stderr.flush()
+# Original value of threading.excepthook
+__excepthook__ = excepthook
+
+
def _make_invoke_excepthook():
# Create a local namespace to ensure that variables remain alive
# when _invoke_excepthook() is called, even if it is called late during