diff options
-rw-r--r-- | Doc/using/cmdline.rst | 7 | ||||
-rw-r--r-- | Lib/test/test_sys.py | 20 | ||||
-rw-r--r-- | Modules/main.c | 1 | ||||
-rw-r--r-- | Python/pythonrun.c | 23 |
4 files changed, 45 insertions, 6 deletions
diff --git a/Doc/using/cmdline.rst b/Doc/using/cmdline.rst index ae661ce..a6a6ecf 100644 --- a/Doc/using/cmdline.rst +++ b/Doc/using/cmdline.rst @@ -467,6 +467,13 @@ if Python was configured with the :option:`--with-pydebug` build option. If set, Python will dump objects and reference counts still alive after shutting down the interpreter. +.. envvar:: PYTHONIOENCODING + + Overrides the encoding used for stdin/stdout/stderr, in the syntax + encodingname:errorhandler, with the :errors part being optional. + + .. versionadded:: 2.6 + .. envvar:: PYTHONMALLOCSTATS diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 231b460..e1bc98d 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -349,6 +349,26 @@ class SysModuleTest(unittest.TestCase): #self.assert_(r[0][1] > 100, r[0][1]) #self.assert_(r[0][2] > 100, r[0][2]) + def test_ioencoding(self): + import subprocess,os + env = dict(os.environ) + + # Test character: cent sign, encoded as 0x4A (ASCII J) in CP424, + # not representable in ASCII. + + env["PYTHONIOENCODING"] = "cp424" + p = subprocess.Popen([sys.executable, "-c", 'print(chr(0xa2))'], + stdout = subprocess.PIPE, env=env) + out = p.stdout.read() + self.assertEqual(out, "\xa2\n".encode("cp424")) + + env["PYTHONIOENCODING"] = "ascii:replace" + p = subprocess.Popen([sys.executable, "-c", 'print(chr(0xa2))'], + stdout = subprocess.PIPE, env=env) + out = p.stdout.read().strip() + self.assertEqual(out, b'?') + + def test_main(): test.support.run_unittest(SysModuleTest) diff --git a/Modules/main.c b/Modules/main.c index 27b8493..b762b0f 100644 --- a/Modules/main.c +++ b/Modules/main.c @@ -96,6 +96,7 @@ static char *usage_5 = "\ PYTHONHOME : alternate <prefix> directory (or <prefix>%c<exec_prefix>).\n\ The default module search path uses %s.\n\ PYTHONCASEOK : ignore case in 'import' statements (Windows).\n\ +PYTHONIOENCODING: Encoding[:errors] used for stdin/stdout/stderr.\n\ "; #ifndef MS_WINDOWS diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 2e93a3a..f2f14ed 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -701,6 +701,7 @@ initstdio(void) PyObject *std = NULL; int status = 0, fd; PyObject * encoding_attr; + char *encoding, *errors; /* Hack to avoid a nasty recursion issue when Python is invoked in verbose mode: pre-import the Latin-1 and UTF-8 codecs */ @@ -730,6 +731,16 @@ initstdio(void) goto error; } + encoding = Py_GETENV("PYTHONIOENCODING"); + if (encoding) { + encoding = strdup(encoding); + errors = strchr(encoding, ':'); + if (errors) { + *errors = '\0'; + errors++; + } + } + /* Set sys.stdin */ fd = fileno(stdin); /* Under some conditions stdin, stdout and stderr may not be connected @@ -745,8 +756,8 @@ initstdio(void) #endif } else { - if (!(std = PyFile_FromFd(fd, "<stdin>", "r", -1, NULL, NULL, - "\n", 0))) { + if (!(std = PyFile_FromFd(fd, "<stdin>", "r", -1, encoding, + errors, "\n", 0))) { goto error; } } /* if (fd < 0) */ @@ -765,8 +776,8 @@ initstdio(void) #endif } else { - if (!(std = PyFile_FromFd(fd, "<stdout>", "w", -1, NULL, NULL, - "\n", 0))) { + if (!(std = PyFile_FromFd(fd, "<stdout>", "w", -1, encoding, + errors, "\n", 0))) { goto error; } } /* if (fd < 0) */ @@ -786,8 +797,8 @@ initstdio(void) #endif } else { - if (!(std = PyFile_FromFd(fd, "<stderr>", "w", -1, NULL, NULL, - "\n", 0))) { + if (!(std = PyFile_FromFd(fd, "<stderr>", "w", -1, encoding, + errors, "\n", 0))) { goto error; } } /* if (fd < 0) */ |