[Python-checkins] cpython: Closes #23234: Refactor subprocess

victor.stinner python-checkins at python.org
Wed Jan 14 17:11:06 CET 2015


https://hg.python.org/cpython/rev/0c5ae257966f
changeset:   94141:0c5ae257966f
user:        Victor Stinner <victor.stinner at gmail.com>
date:        Wed Jan 14 17:07:59 2015 +0100
summary:
  Closes #23234: Refactor subprocess

Use new OSError exceptions, factorize stdin.write() code.

files:
  Lib/subprocess.py |  58 ++++++++++++++--------------------
  1 files changed, 24 insertions(+), 34 deletions(-)


diff --git a/Lib/subprocess.py b/Lib/subprocess.py
--- a/Lib/subprocess.py
+++ b/Lib/subprocess.py
@@ -920,6 +920,22 @@
             self._devnull = os.open(os.devnull, os.O_RDWR)
         return self._devnull
 
+    def _stdin_write(self, input):
+        if input:
+            try:
+                self.stdin.write(input)
+            except BrokenPipeError:
+                # communicate() must ignore broken pipe error
+                pass
+            except OSError as e:
+                if e.errno == errno.EINVAL and self.poll() is not None:
+                    # Issue #19612: On Windows, stdin.write() fails with EINVAL
+                    # if the process already exited before the write
+                    pass
+                else:
+                    raise
+        self.stdin.close()
+
     def communicate(self, input=None, timeout=None):
         """Interact with process: Send data to stdin.  Read data from
         stdout and stderr, until end-of-file is reached.  Wait for
@@ -945,13 +961,7 @@
             stdout = None
             stderr = None
             if self.stdin:
-                if input:
-                    try:
-                        self.stdin.write(input)
-                    except OSError as e:
-                        if e.errno != errno.EPIPE and e.errno != errno.EINVAL:
-                            raise
-                self.stdin.close()
+                self._stdin_write(input)
             elif self.stdout:
                 stdout = _eintr_retry_call(self.stdout.read)
                 self.stdout.close()
@@ -1200,21 +1210,7 @@
                 self.stderr_thread.start()
 
             if self.stdin:
-                if input is not None:
-                    try:
-                        self.stdin.write(input)
-                    except OSError as e:
-                        if e.errno == errno.EPIPE:
-                            # communicate() should ignore pipe full error
-                            pass
-                        elif (e.errno == errno.EINVAL
-                              and self.poll() is not None):
-                            # Issue #19612: stdin.write() fails with EINVAL
-                            # if the process already exited before the write
-                            pass
-                        else:
-                            raise
-                self.stdin.close()
+                self._stdin_write(input)
 
             # Wait for the reader threads, or time out.  If we time out, the
             # threads remain reading and the fds left open in case the user
@@ -1425,9 +1421,8 @@
             if errpipe_data:
                 try:
                     _eintr_retry_call(os.waitpid, self.pid, 0)
-                except OSError as e:
-                    if e.errno != errno.ECHILD:
-                        raise
+                except ChildProcessError:
+                    pass
                 try:
                     exception_name, hex_errno, err_msg = (
                             errpipe_data.split(b':', 2))
@@ -1511,9 +1506,7 @@
             """All callers to this function MUST hold self._waitpid_lock."""
             try:
                 (pid, sts) = _eintr_retry_call(os.waitpid, self.pid, wait_flags)
-            except OSError as e:
-                if e.errno != errno.ECHILD:
-                    raise
+            except ChildProcessError:
                 # This happens if SIGCLD is set to be ignored or waiting
                 # for child processes has otherwise been disabled for our
                 # process.  This child is dead, we can't get the status.
@@ -1625,12 +1618,9 @@
                                                self._input_offset + _PIPE_BUF]
                             try:
                                 self._input_offset += os.write(key.fd, chunk)
-                            except OSError as e:
-                                if e.errno == errno.EPIPE:
-                                    selector.unregister(key.fileobj)
-                                    key.fileobj.close()
-                                else:
-                                    raise
+                            except BrokenPipeError:
+                                selector.unregister(key.fileobj)
+                                key.fileobj.close()
                             else:
                                 if self._input_offset >= len(self._input):
                                     selector.unregister(key.fileobj)

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


More information about the Python-checkins mailing list