bpo-13601: always use line-buffering for sys.stderr (GH-17646)

This commit is contained in:
Jendrik Seipp 2020-01-01 23:21:43 +01:00 committed by Antoine Pitrou
parent 46abfc1416
commit 5b9077134c
5 changed files with 33 additions and 4 deletions

View 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::

View 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'):

View File

@ -1510,6 +1510,7 @@ Steven Scott
Nick Seidenman
Michael Seifert
Žiga Seilnacht
Jendrik Seipp
Michael Selik
Yury Selivanov
Fred Sells

View File

@ -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.)

View 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;