diff --git a/Doc/library/test.rst b/Doc/library/test.rst index a8dc35476fc..699db14596f 100644 --- a/Doc/library/test.rst +++ b/Doc/library/test.rst @@ -607,6 +607,15 @@ The :mod:`test.support` module defines the following functions: target of the "as" clause, if there is one. +.. function:: flush_std_streams() + + Call the ``flush()`` method on :data:`sys.stdout` and then on + :data:`sys.stderr`. It can be used to make sure that the logs order is + consistent before writing into stderr. + + .. versionadded:: 3.11 + + .. function:: print_warning(msg) Print a warning into :data:`sys.__stderr__`. Format the message as: diff --git a/Lib/test/libregrtest/utils.py b/Lib/test/libregrtest/utils.py index ad18b50f5db..c71467a5192 100644 --- a/Lib/test/libregrtest/utils.py +++ b/Lib/test/libregrtest/utils.py @@ -68,20 +68,13 @@ def print_warning(msg): orig_unraisablehook = None -def flush_std_streams(): - if sys.stdout is not None: - sys.stdout.flush() - if sys.stderr is not None: - sys.stderr.flush() - - def regrtest_unraisable_hook(unraisable): global orig_unraisablehook support.environment_altered = True print_warning("Unraisable exception") old_stderr = sys.stderr try: - flush_std_streams() + support.flush_std_streams() sys.stderr = sys.__stderr__ orig_unraisablehook(unraisable) sys.stderr.flush() @@ -104,7 +97,7 @@ def regrtest_threading_excepthook(args): print_warning(f"Uncaught thread exception: {args.exc_type.__name__}") old_stderr = sys.stderr try: - flush_std_streams() + support.flush_std_streams() sys.stderr = sys.__stderr__ orig_threading_excepthook(args) sys.stderr.flush() diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index b29f438e52c..0bbe813775c 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -1167,7 +1167,16 @@ def run_doctest(module, verbosity=None, optionflags=0): #======================================================================= # Support for saving and restoring the imported modules. +def flush_std_streams(): + if sys.stdout is not None: + sys.stdout.flush() + if sys.stderr is not None: + sys.stderr.flush() + + def print_warning(msg): + # bpo-45410: Explicitly flush stdout to keep logs in order + flush_std_streams() # bpo-39983: Print into sys.__stderr__ to display the warning even # when sys.stderr is captured temporarily by a test for line in msg.splitlines():