-
-
Notifications
You must be signed in to change notification settings - Fork 31.9k
bpo-13601: always use line-buffering for sys.stderr #17646
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, but it would be nice if you could add a test, for example in Lib/test/test_cmd_line.py
.
Thanks for your comments! I hope my changes address them adequately. |
Lib/test/test_cmd_line.py
Outdated
code = f'import os, sys; {buf}.write({txt1!r}); {buf}.write({txt2!r}); os._exit(0)' | ||
rc, out, err = assert_python_ok('-c', code) | ||
self.assertEqual(out, out_ok) | ||
self.assertEqual(err, err_ok) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure that a functional test is required here to validate manually that buffered are flushed properly. Maybe testing the following attributes are enough?
>>> sys.stdout.write_through, sys.stdout.write_through
(False, False)
What do you think @pitrou?
My worry is that functional tests are more likely to fail and so give me more to work to maintain the CI :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added non-functional tests and removed the functional tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the documentation update!
Lib/test/test_cmd_line.py
Outdated
('sys.stderr.line_buffering', True), | ||
] | ||
for attr, value in cases: | ||
self.assertEqual(get_value(attr), value, f'{attr} is not {value}') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest to rewrite the test to run Python a single time rather than 6 times, to make the test faster:
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,
text=True, check=True)
self.assertEqual(proc.stdout,
'False False False\n'
'True False True\n')
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point! I used your code, but added stderr=subprocess.PIPE
to ensure that sys.stderr
is not a TTY (without this both the old and the new code would pass the test).
@@ -0,0 +1,2 @@ | |||
``sys.stderr`` is always line-buffered now, even if ``stderr`` is |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless it is unbuffered.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is your first contribution. Please add your name in Misc/ACKS
. You can also add "Patch by yourname." here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I added some explanations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. @serhiy-storchaka, @pitrou: does it look good to you? I let you merge the change.
There's a fun Python 3.9 only test case failure, where "Daemon started" is output after the error message from parsing options. I ended up needing to bisect to figure out why this breaks consistently on Python 3.9. The issue is caused by python/cpython#17646 (which fixes a surprisingly old issue). I'm biased because I just spent some time figuring this out, but maybe it should be mentioned in the What's New.
There's a fun Python 3.9 only test case failure, where "Daemon started" is output after the error message from parsing options. I ended up needing to bisect to figure out why this consistently breaks on Python 3.9. The issue is caused by python/cpython#17646 (which fixes a surprisingly old BPO).
There's a fun Python 3.9 only test case failure, where "Daemon started" is output after the error message from parsing options. I ended up needing to bisect to figure out why this consistently breaks on Python 3.9. The issue is caused by python/cpython#17646 (which fixes a surprisingly old BPO). Co-authored-by: hauntsaninja <>
Fixes https://bugs.python.org/issue13601
https://bugs.python.org/issue13601