Issue #5870: Add subprocess.DEVNULL constant.
This commit is contained in:
parent
09bb8f46aa
commit
ba102ec10d
|
@ -125,12 +125,14 @@ This module defines one class called :class:`Popen`:
|
|||
|
||||
*stdin*, *stdout* and *stderr* specify the executed programs' standard input,
|
||||
standard output and standard error file handles, respectively. Valid values
|
||||
are :data:`PIPE`, an existing file descriptor (a positive integer), an
|
||||
existing :term:`file object`, and ``None``. :data:`PIPE` indicates that a
|
||||
new pipe to the child should be created. With ``None``, no redirection will
|
||||
occur; the child's file handles will be inherited from the parent. Additionally,
|
||||
*stderr* can be :data:`STDOUT`, which indicates that the stderr data from the
|
||||
applications should be captured into the same file handle as for stdout.
|
||||
are :data:`PIPE`, :data:`DEVNULL`, an existing file descriptor (a positive
|
||||
integer), an existing :term:`file object`, and ``None``. :data:`PIPE`
|
||||
indicates that a new pipe to the child should be created. :data:`DEVNULL`
|
||||
indicates that the special file :data:`os.devnull` will be used. With ``None``,
|
||||
no redirection will occur; the child's file handles will be inherited from
|
||||
the parent. Additionally, *stderr* can be :data:`STDOUT`, which indicates
|
||||
that the stderr data from the applications should be captured into the same
|
||||
file handle as for stdout.
|
||||
|
||||
If *preexec_fn* is set to a callable object, this object will be called in the
|
||||
child process just before the child is executed.
|
||||
|
@ -229,6 +231,15 @@ This module defines one class called :class:`Popen`:
|
|||
Added context manager support.
|
||||
|
||||
|
||||
.. data:: DEVNULL
|
||||
|
||||
Special value that can be used as the *stdin*, *stdout* or *stderr* argument
|
||||
to :class:`Popen` and indicates that the special file :data:`os.devnull`
|
||||
will be used.
|
||||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
|
||||
.. data:: PIPE
|
||||
|
||||
Special value that can be used as the *stdin*, *stdout* or *stderr* argument
|
||||
|
|
|
@ -431,7 +431,7 @@ else:
|
|||
return fds
|
||||
|
||||
__all__ = ["Popen", "PIPE", "STDOUT", "call", "check_call", "getstatusoutput",
|
||||
"getoutput", "check_output", "CalledProcessError"]
|
||||
"getoutput", "check_output", "CalledProcessError", "DEVNULL"]
|
||||
|
||||
if mswindows:
|
||||
from _subprocess import CREATE_NEW_CONSOLE, CREATE_NEW_PROCESS_GROUP
|
||||
|
@ -456,6 +456,7 @@ def _cleanup():
|
|||
|
||||
PIPE = -1
|
||||
STDOUT = -2
|
||||
DEVNULL = -3
|
||||
|
||||
|
||||
def _eintr_retry_call(func, *args):
|
||||
|
@ -800,6 +801,10 @@ class Popen(object):
|
|||
# Child is still running, keep us alive until we can wait on it.
|
||||
_active.append(self)
|
||||
|
||||
def _get_devnull(self):
|
||||
if not hasattr(self, '_devnull'):
|
||||
self._devnull = os.open(os.devnull, os.O_RDWR)
|
||||
return self._devnull
|
||||
|
||||
def communicate(self, input=None, timeout=None):
|
||||
"""Interact with process: Send data to stdin. Read data from
|
||||
|
@ -889,6 +894,8 @@ class Popen(object):
|
|||
p2cread, _ = _subprocess.CreatePipe(None, 0)
|
||||
elif stdin == PIPE:
|
||||
p2cread, p2cwrite = _subprocess.CreatePipe(None, 0)
|
||||
elif stdin == DEVNULL:
|
||||
p2cread = msvcrt.get_osfhandle(self._get_devnull())
|
||||
elif isinstance(stdin, int):
|
||||
p2cread = msvcrt.get_osfhandle(stdin)
|
||||
else:
|
||||
|
@ -902,6 +909,8 @@ class Popen(object):
|
|||
_, c2pwrite = _subprocess.CreatePipe(None, 0)
|
||||
elif stdout == PIPE:
|
||||
c2pread, c2pwrite = _subprocess.CreatePipe(None, 0)
|
||||
elif stdout == DEVNULL:
|
||||
c2pwrite = msvcrt.get_osfhandle(self._get_devnull())
|
||||
elif isinstance(stdout, int):
|
||||
c2pwrite = msvcrt.get_osfhandle(stdout)
|
||||
else:
|
||||
|
@ -917,6 +926,8 @@ class Popen(object):
|
|||
errread, errwrite = _subprocess.CreatePipe(None, 0)
|
||||
elif stderr == STDOUT:
|
||||
errwrite = c2pwrite
|
||||
elif stderr == DEVNULL:
|
||||
errwrite = msvcrt.get_osfhandle(self._get_devnull())
|
||||
elif isinstance(stderr, int):
|
||||
errwrite = msvcrt.get_osfhandle(stderr)
|
||||
else:
|
||||
|
@ -1026,6 +1037,8 @@ class Popen(object):
|
|||
c2pwrite.Close()
|
||||
if errwrite != -1:
|
||||
errwrite.Close()
|
||||
if hasattr(self, '_devnull'):
|
||||
os.close(self._devnull)
|
||||
|
||||
# Retain the process handle, but close the thread handle
|
||||
self._child_created = True
|
||||
|
@ -1159,6 +1172,8 @@ class Popen(object):
|
|||
pass
|
||||
elif stdin == PIPE:
|
||||
p2cread, p2cwrite = _create_pipe()
|
||||
elif stdin == DEVNULL:
|
||||
p2cread = self._get_devnull()
|
||||
elif isinstance(stdin, int):
|
||||
p2cread = stdin
|
||||
else:
|
||||
|
@ -1169,6 +1184,8 @@ class Popen(object):
|
|||
pass
|
||||
elif stdout == PIPE:
|
||||
c2pread, c2pwrite = _create_pipe()
|
||||
elif stdout == DEVNULL:
|
||||
c2pwrite = self._get_devnull()
|
||||
elif isinstance(stdout, int):
|
||||
c2pwrite = stdout
|
||||
else:
|
||||
|
@ -1181,6 +1198,8 @@ class Popen(object):
|
|||
errread, errwrite = _create_pipe()
|
||||
elif stderr == STDOUT:
|
||||
errwrite = c2pwrite
|
||||
elif stderr == DEVNULL:
|
||||
errwrite = self._get_devnull()
|
||||
elif isinstance(stderr, int):
|
||||
errwrite = stderr
|
||||
else:
|
||||
|
@ -1374,6 +1393,8 @@ class Popen(object):
|
|||
os.close(c2pwrite)
|
||||
if errwrite != -1 and errread != -1:
|
||||
os.close(errwrite)
|
||||
if hasattr(self, '_devnull'):
|
||||
os.close(self._devnull)
|
||||
|
||||
# Wait for exec to fail or succeed; possibly raising an
|
||||
# exception (limited in size)
|
||||
|
|
|
@ -323,6 +323,31 @@ class ProcessTestCase(BaseTestCase):
|
|||
rc = subprocess.call([sys.executable, "-c", cmd], stdout=1)
|
||||
self.assertEqual(rc, 2)
|
||||
|
||||
def test_stdout_devnull(self):
|
||||
p = subprocess.Popen([sys.executable, "-c",
|
||||
'for i in range(10240):'
|
||||
'print("x" * 1024)'],
|
||||
stdout=subprocess.DEVNULL)
|
||||
p.wait()
|
||||
self.assertEqual(p.stdout, None)
|
||||
|
||||
def test_stderr_devnull(self):
|
||||
p = subprocess.Popen([sys.executable, "-c",
|
||||
'import sys\n'
|
||||
'for i in range(10240):'
|
||||
'sys.stderr.write("x" * 1024)'],
|
||||
stderr=subprocess.DEVNULL)
|
||||
p.wait()
|
||||
self.assertEqual(p.stderr, None)
|
||||
|
||||
def test_stdin_devnull(self):
|
||||
p = subprocess.Popen([sys.executable, "-c",
|
||||
'import sys;'
|
||||
'sys.stdin.read(1)'],
|
||||
stdin=subprocess.DEVNULL)
|
||||
p.wait()
|
||||
self.assertEqual(p.stdin, None)
|
||||
|
||||
def test_cwd(self):
|
||||
tmpdir = tempfile.gettempdir()
|
||||
# We cannot use os.path.realpath to canonicalize the path,
|
||||
|
|
Loading…
Reference in New Issue