[Python-checkins] cpython (3.2): Issue #7111: Python can now be run without a stdin, stdout or stderr stream.

antoine.pitrou python-checkins at python.org
Mon Nov 28 19:16:23 CET 2011


http://hg.python.org/cpython/rev/f15943505db0
changeset:   73775:f15943505db0
branch:      3.2
parent:      73773:661fb211f220
user:        Antoine Pitrou <solipsis at pitrou.net>
date:        Mon Nov 28 19:08:36 2011 +0100
summary:
  Issue #7111: Python can now be run without a stdin, stdout or stderr stream.

It was already the case with Python 2.  However, the corresponding
sys module entries are now set to None (instead of an unusable file object).

files:
  Lib/test/test_cmd_line.py |  39 +++++++++++++++++++++++++++
  Misc/NEWS                 |   4 ++
  Python/pythonrun.c        |  31 +++++++++++----------
  3 files changed, 59 insertions(+), 15 deletions(-)


diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py
--- a/Lib/test/test_cmd_line.py
+++ b/Lib/test/test_cmd_line.py
@@ -291,6 +291,45 @@
         rc, out, err = assert_python_ok('-c', code)
         self.assertEqual(b'', err)
 
+    # Issue #7111: Python should work without standard streams
+
+    @unittest.skipIf(os.name != 'posix', "test needs POSIX semantics")
+    def _test_no_stdio(self, streams):
+        code = """if 1:
+            import os, sys
+            for i, s in enumerate({streams}):
+                if getattr(sys, s) is not None:
+                    os._exit(i + 1)
+            os._exit(42)""".format(streams=streams)
+        def preexec():
+            if 'stdin' in streams:
+                os.close(0)
+            if 'stdout' in streams:
+                os.close(1)
+            if 'stderr' in streams:
+                os.close(2)
+        p = subprocess.Popen(
+            [sys.executable, "-E", "-c", code],
+            stdin=subprocess.PIPE,
+            stdout=subprocess.PIPE,
+            stderr=subprocess.PIPE,
+            preexec_fn=preexec)
+        out, err = p.communicate()
+        self.assertEqual(test.support.strip_python_stderr(err), b'')
+        self.assertEqual(p.returncode, 42)
+
+    def test_no_stdin(self):
+        self._test_no_stdio(['stdin'])
+
+    def test_no_stdout(self):
+        self._test_no_stdio(['stdout'])
+
+    def test_no_stderr(self):
+        self._test_no_stdio(['stderr'])
+
+    def test_no_std_streams(self):
+        self._test_no_stdio(['stdin', 'stdout', 'stderr'])
+
 
 def test_main():
     test.support.run_unittest(CmdLineTest)
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,10 @@
 Core and Builtins
 -----------------
 
+- Issue #7111: Python can now be run without a stdin, stdout or stderr
+  stream.  It was already the case with Python 2.  However, the corresponding
+  sys module entries are now set to None (instead of an unusable file object).
+
 - Issue #13436: Fix a bogus error message when an AST object was passed
   an invalid integer value.
 
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -892,6 +892,19 @@
     return NULL;
 }
 
+static int
+is_valid_fd(int fd)
+{
+    int dummy_fd;
+    if (fd < 0 || !_PyVerify_fd(fd))
+        return 0;
+    dummy_fd = dup(fd);
+    if (dummy_fd < 0)
+        return 0;
+    close(dummy_fd);
+    return 1;
+}
+
 /* Initialize sys.stdin, stdout, stderr and builtins.open */
 static int
 initstdio(void)
@@ -951,13 +964,9 @@
      * and fileno() may point to an invalid file descriptor. For example
      * GUI apps don't have valid standard streams by default.
      */
-    if (fd < 0) {
-#ifdef MS_WINDOWS
+    if (!is_valid_fd(fd)) {
         std = Py_None;
         Py_INCREF(std);
-#else
-        goto error;
-#endif
     }
     else {
         std = create_stdio(iomod, fd, 0, "<stdin>", encoding, errors);
@@ -970,13 +979,9 @@
 
     /* Set sys.stdout */
     fd = fileno(stdout);
-    if (fd < 0) {
-#ifdef MS_WINDOWS
+    if (!is_valid_fd(fd)) {
         std = Py_None;
         Py_INCREF(std);
-#else
-        goto error;
-#endif
     }
     else {
         std = create_stdio(iomod, fd, 1, "<stdout>", encoding, errors);
@@ -990,13 +995,9 @@
 #if 1 /* Disable this if you have trouble debugging bootstrap stuff */
     /* Set sys.stderr, replaces the preliminary stderr */
     fd = fileno(stderr);
-    if (fd < 0) {
-#ifdef MS_WINDOWS
+    if (!is_valid_fd(fd)) {
         std = Py_None;
         Py_INCREF(std);
-#else
-        goto error;
-#endif
     }
     else {
         std = create_stdio(iomod, fd, 1, "<stderr>", encoding, "backslashreplace");

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list