]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-13601: always use line-buffering for sys.stderr (GH-17646)
authorJendrik Seipp <jendrikseipp@gmail.com>
Wed, 1 Jan 2020 22:21:43 +0000 (23:21 +0100)
committerAntoine Pitrou <antoine@python.org>
Wed, 1 Jan 2020 22:21:43 +0000 (23:21 +0100)
Doc/library/sys.rst
Lib/test/test_cmd_line.py
Misc/ACKS
Misc/NEWS.d/next/Core and Builtins/2019-12-17-22-32-11.bpo-13601.vNP4LC.rst [new file with mode: 0644]
Python/pylifecycle.c

index a824fb95e8ecfcd956228eaba0eaf54edc4432f8..0aae263ff5f4c1f93c66d8fab40fdd8e2021b384 100644 (file)
@@ -1446,9 +1446,15 @@ always available.
      for the Windows console, this only applies when
      :envvar:`PYTHONLEGACYWINDOWSSTDIO` is also set.
 
-   * When interactive, ``stdout`` and ``stderr`` streams are line-buffered.
-     Otherwise, they are block-buffered like regular text files.  You can
-     override this value with the :option:`-u` command-line option.
+   * When interactive, the ``stdout`` stream is line-buffered. Otherwise,
+     it is block-buffered like regular text files.  The ``stderr`` stream
+     is line-buffered in both cases.  You can make both streams unbuffered
+     by passing the :option:`-u` command-line option or setting the
+     :envvar:`PYTHONUNBUFFERED` environment variable.
+
+   .. versionchanged:: 3.9
+      Non-interactive ``stderr`` is now line-buffered instead of fully
+      buffered.
 
    .. note::
 
index 47810020dd353ccc0c4554f1df7351b9ef38e51b..ee96473322dba084596bda51f375213a56d2253e 100644 (file)
@@ -6,6 +6,7 @@ import os
 import subprocess
 import sys
 import tempfile
+import textwrap
 import unittest
 from test import support
 from test.support.script_helper import (
@@ -219,6 +220,21 @@ class CmdLineTest(unittest.TestCase):
         )
         check_output(text)
 
+    def test_non_interactive_output_buffering(self):
+        code = textwrap.dedent("""
+            import sys
+            out = sys.stdout
+            print(out.isatty(), out.write_through, out.line_buffering)
+            err = sys.stderr
+            print(err.isatty(), err.write_through, err.line_buffering)
+        """)
+        args = [sys.executable, '-c', code]
+        proc = subprocess.run(args, stdout=subprocess.PIPE,
+                              stderr=subprocess.PIPE, text=True, check=True)
+        self.assertEqual(proc.stdout,
+                         'False False False\n'
+                         'False False True\n')
+
     def test_unbuffered_output(self):
         # Test expected operation of the '-u' switch
         for stream in ('stdout', 'stderr'):
index 5ecbac13e0bb4a4f3f4bcca1c9059be1b20a4f1c..d3e683d4a085fdff444b72da7d2f26c47a6fc8af 100644 (file)
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -1510,6 +1510,7 @@ Steven Scott
 Nick Seidenman
 Michael Seifert
 Žiga Seilnacht
+Jendrik Seipp
 Michael Selik
 Yury Selivanov
 Fred Sells
diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-12-17-22-32-11.bpo-13601.vNP4LC.rst b/Misc/NEWS.d/next/Core and Builtins/2019-12-17-22-32-11.bpo-13601.vNP4LC.rst
new file mode 100644 (file)
index 0000000..f2c9495
--- /dev/null
@@ -0,0 +1,6 @@
+By default, ``sys.stderr`` is line-buffered now, even if ``stderr`` is
+redirected to a file. You can still make ``sys.stderr`` unbuffered by
+passing the :option:`-u` command-line option or setting the
+:envvar:`PYTHONUNBUFFERED` environment variable.
+
+(Contributed by Jendrik Seipp in bpo-13601.)
index 4f05dfc349033b870dcee6a02a74013688184195..94bbbdb560e797a602f4511bf00fb4c5ca87c163 100644 (file)
@@ -1817,7 +1817,7 @@ create_stdio(const PyConfig *config, PyObject* io,
         write_through = Py_True;
     else
         write_through = Py_False;
-    if (isatty && buffered_stdio)
+    if (buffered_stdio && (isatty || fd == fileno(stderr)))
         line_buffering = Py_True;
     else
         line_buffering = Py_False;