Skip to content

Commit fc43511

Browse files
Issue #25339: PYTHONIOENCODING now has priority over locale in setting the
error handler for stdin and stdout.
1 parent 731b1b1 commit fc43511

File tree

3 files changed

+35
-14
lines changed

3 files changed

+35
-14
lines changed

Lib/test/test_sys.py

+23-4
Original file line numberDiff line numberDiff line change
@@ -691,8 +691,10 @@ def c_locale_get_error_handler(self, isolated=False, encoding=None):
691691
args = [sys.executable, "-c", code]
692692
if isolated:
693693
args.append("-I")
694-
elif encoding:
694+
if encoding is not None:
695695
env['PYTHONIOENCODING'] = encoding
696+
else:
697+
env.pop('PYTHONIOENCODING', None)
696698
p = subprocess.Popen(args,
697699
stdout=subprocess.PIPE,
698700
stderr=subprocess.STDOUT,
@@ -709,14 +711,31 @@ def test_c_locale_surrogateescape(self):
709711
'stderr: backslashreplace\n')
710712

711713
# replace the default error handler
712-
out = self.c_locale_get_error_handler(encoding=':strict')
714+
out = self.c_locale_get_error_handler(encoding=':ignore')
713715
self.assertEqual(out,
714-
'stdin: strict\n'
715-
'stdout: strict\n'
716+
'stdin: ignore\n'
717+
'stdout: ignore\n'
716718
'stderr: backslashreplace\n')
717719

718720
# force the encoding
719721
out = self.c_locale_get_error_handler(encoding='iso8859-1')
722+
self.assertEqual(out,
723+
'stdin: strict\n'
724+
'stdout: strict\n'
725+
'stderr: backslashreplace\n')
726+
out = self.c_locale_get_error_handler(encoding='iso8859-1:')
727+
self.assertEqual(out,
728+
'stdin: strict\n'
729+
'stdout: strict\n'
730+
'stderr: backslashreplace\n')
731+
732+
# have no any effect
733+
out = self.c_locale_get_error_handler(encoding=':')
734+
self.assertEqual(out,
735+
'stdin: surrogateescape\n'
736+
'stdout: surrogateescape\n'
737+
'stderr: backslashreplace\n')
738+
out = self.c_locale_get_error_handler(encoding='')
720739
self.assertEqual(out,
721740
'stdin: surrogateescape\n'
722741
'stdout: surrogateescape\n'

Misc/NEWS

+3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ Release date: tba
1010
Core and Builtins
1111
-----------------
1212

13+
- Issue #25339: PYTHONIOENCODING now has priority over locale in setting the
14+
error handler for stdin and stdout.
15+
1316
- Issue #26494: Fixed crash on iterating exhausting iterators.
1417
Affected classes are generic sequence iterators, iterators of str, bytes,
1518
bytearray, list, tuple, set, frozenset, dict, OrderedDict, corresponding

Python/pylifecycle.c

+9-10
Original file line numberDiff line numberDiff line change
@@ -1135,15 +1135,6 @@ initstdio(void)
11351135
encoding = _Py_StandardStreamEncoding;
11361136
errors = _Py_StandardStreamErrors;
11371137
if (!encoding || !errors) {
1138-
if (!errors) {
1139-
/* When the LC_CTYPE locale is the POSIX locale ("C locale"),
1140-
stdin and stdout use the surrogateescape error handler by
1141-
default, instead of the strict error handler. */
1142-
char *loc = setlocale(LC_CTYPE, NULL);
1143-
if (loc != NULL && strcmp(loc, "C") == 0)
1144-
errors = "surrogateescape";
1145-
}
1146-
11471138
pythonioencoding = Py_GETENV("PYTHONIOENCODING");
11481139
if (pythonioencoding) {
11491140
char *err;
@@ -1156,14 +1147,22 @@ initstdio(void)
11561147
if (err) {
11571148
*err = '\0';
11581149
err++;
1159-
if (*err && !_Py_StandardStreamErrors) {
1150+
if (*err && !errors) {
11601151
errors = err;
11611152
}
11621153
}
11631154
if (*pythonioencoding && !encoding) {
11641155
encoding = pythonioencoding;
11651156
}
11661157
}
1158+
if (!errors && !(pythonioencoding && *pythonioencoding)) {
1159+
/* When the LC_CTYPE locale is the POSIX locale ("C locale"),
1160+
stdin and stdout use the surrogateescape error handler by
1161+
default, instead of the strict error handler. */
1162+
char *loc = setlocale(LC_CTYPE, NULL);
1163+
if (loc != NULL && strcmp(loc, "C") == 0)
1164+
errors = "surrogateescape";
1165+
}
11671166
}
11681167

11691168
/* Set sys.stdin */

0 commit comments

Comments
 (0)