Skip to content

Commit c49dfcc

Browse files
author
Victor Stinner
committed
Issue #3798: Write sys.exit() message to sys.stderr to use stderr encoding and
error handler, instead of writing to the C stderr file in utf-8
1 parent 7c4d7d3 commit c49dfcc

File tree

3 files changed

+30
-1
lines changed

3 files changed

+30
-1
lines changed

Lib/test/test_sys.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,26 @@ def test_exit(self):
178178
"raise SystemExit(47)"])
179179
self.assertEqual(rc, 47)
180180

181+
def check_exit_message(code, expected, env=None):
182+
process = subprocess.Popen([sys.executable, "-c", code],
183+
stderr=subprocess.PIPE, env=env)
184+
stdout, stderr = process.communicate()
185+
self.assertEqual(process.returncode, 1)
186+
self.assertTrue(stderr.startswith(expected),
187+
"%s doesn't start with %s" % (repr(stderr), repr(expected)))
188+
189+
# test that stderr buffer if flushed before the exit message is written
190+
# into stderr
191+
check_exit_message(
192+
r'import sys; sys.stderr.write("unflushed,"); sys.exit("message")',
193+
b"unflushed,message")
194+
195+
# test that the unicode message is encoded to the stderr encoding
196+
env = os.environ.copy()
197+
env['PYTHONIOENCODING'] = 'latin-1'
198+
check_exit_message(
199+
r'import sys; sys.exit(u"h\xe9")',
200+
b"h\xe9", env=env)
181201

182202
def test_getdefaultencoding(self):
183203
if test.test_support.have_unicode:

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ What's New in Python 2.7 Release Candidate 1?
1212
Core and Builtins
1313
-----------------
1414

15+
- Issue #3798: Write sys.exit() message to sys.stderr to use stderr encoding
16+
and error handler, instead of writing to the C stderr file in utf-8
17+
1518
- Issue #7902: When using explicit relative import syntax, don't try implicit
1619
relative import semantics.
1720

Python/pythonrun.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1106,7 +1106,13 @@ handle_system_exit(void)
11061106
if (PyInt_Check(value))
11071107
exitcode = (int)PyInt_AsLong(value);
11081108
else {
1109-
PyObject_Print(value, stderr, Py_PRINT_RAW);
1109+
PyObject *sys_stderr = PySys_GetObject("stderr");
1110+
if (sys_stderr != NULL && sys_stderr != Py_None) {
1111+
PyFile_WriteObject(value, sys_stderr, Py_PRINT_RAW);
1112+
} else {
1113+
PyObject_Print(value, stderr, Py_PRINT_RAW);
1114+
fflush(stderr);
1115+
}
11101116
PySys_WriteStderr("\n");
11111117
exitcode = 1;
11121118
}

0 commit comments

Comments
 (0)