diff --git a/Lib/site.py b/Lib/site.py index ad1146332b..12c1e0a64f 100644 --- a/Lib/site.py +++ b/Lib/site.py @@ -638,3 +638,47 @@ def _script(): if __name__ == '__main__': _script() + +import traceback + +def myhook(exc_type, exc_value, exc_tb, msg, obj, + # local copies of functions to attempt to get them + # during Python finalization + print_tb=traceback.print_tb, + _getframe=sys._getframe, + extract_stack=traceback.extract_stack, + print_list=traceback.print_list, + open=open): + + global hook_file + if hook_file is None: + hook_file = open(os.path.expanduser("~/unraisable.txt"), "a") + file = hook_file + + print("X" * 60, file=file) + if obj is not None: + if msg is None: + msg = 'Exception ignored in' + print(f"{msg}: {obj!r}", file=file) + elif msg is not None: + print(f"{msg}:", file=file) + + if exc_tb is not None: + try: + print_tb(exc_tb) + except Exception: + # Continue even if printing the traceback fails: + # always try to display the exception type and value + pass + + print(f"{exc_type.__name__}: {exc_value}", file=file) + + stack = extract_stack(_getframe(1)) + if stack: + print('Traceback (most recent call last):', file=file) + print_list(stack, file=file) + + file.flush() + +hook_file = None +sys.unraisablehook = myhook diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index 9e60d960ab..6ba220f542 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -3034,3 +3034,13 @@ def collision_stats(nbins, nballs): collisions = k - occupied var = dn*(dn-1)*((dn-2)/dn)**k + meanempty * (1 - meanempty) return float(collisions), float(var.sqrt()) + + +def _ignore_unraisable(*args): + pass + + +@contextlib.contextmanager +def ignore_unraisable_exc(): + with swap_attr(sys, 'unraisablehook', _ignore_unraisable): + yield diff --git a/Lib/test/test_raise.py b/Lib/test/test_raise.py index c1ef154a9a..9511bee78a 100644 --- a/Lib/test/test_raise.py +++ b/Lib/test/test_raise.py @@ -459,7 +459,7 @@ class TestContext(unittest.TestCase): self.assertNotEqual(e.__context__, None) self.assertIsInstance(e.__context__, AttributeError) - with support.captured_output("stderr"): + with support.ignore_unraisable_exc(): f() class TestRemovedFunctionality(unittest.TestCase): diff --git a/Lib/test/test_yield_from.py b/Lib/test/test_yield_from.py index ce21c3df81..cba1cae5e7 100644 --- a/Lib/test/test_yield_from.py +++ b/Lib/test/test_yield_from.py @@ -562,7 +562,7 @@ class TestPEP380Operation(unittest.TestCase): self.assertEqual(next(gi), 1) gi.throw(AttributeError) - with captured_stderr() as output: + if 1: #with captured_stderr() as output: gi = g() self.assertEqual(next(gi), 1) gi.close()