diff --git a/Lib/subprocess.py b/Lib/subprocess.py --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -538,6 +538,14 @@ retcode = call(["ls", "-l"]) """ + if PIPE in popenargs or PIPE in kwargs.values(): + warnings.warn("Do not use PIPE with this function. " + "The child process will block if it generates enough output to a " + "pipe to fill up the OS pipe buffer as the pipes are not being " + "read from/written to. " + "ValueError will be raised in 3.6. " + "Use DEVNULL to discard output/provide empty input instead.", + DeprecationWarning, 2) with Popen(*popenargs, **kwargs) as p: try: return p.wait(timeout=timeout) diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -117,6 +117,27 @@ "import sys; sys.exit(47)"]) self.assertEqual(rc, 47) + def test_call_pipe_arg(self): + # call() function with PIPE argument + call = subprocess.call + cmd = [sys.executable, "-c", "import sys; sys.exit(47)"] + kwargs = dict(stdout=subprocess.PIPE) + if sys.version_info[:2] >= (3, 6): + self.assertEqual(call(cmd), 47) + with self.assertRaises(ValueError): + call(cmd, **kwargs) + else: # remove this part in 3.6+, + # don't forget to remove the warning from docs too + with warnings.catch_warnings(record=True) as w: + warnings.resetwarnings() # clear all filters + warnings.simplefilter('ignore') # ignore all + warnings.simplefilter('always', DeprecationWarning) # add filter + self.assertEqual(call(cmd), 47) + self.assertFalse(w) + self.assertEqual(call(cmd, **kwargs), 47) + self.assertTrue(w) + self.assertTrue(issubclass(w[-1].category, DeprecationWarning)) + def test_call_timeout(self): # call() function with timeout argument; we want to test that the child # process gets killed when the timeout expires. If the child isn't