Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b3f194d

Browse files
Issue #16903: Popen.communicate() on Unix now accepts strings when
universal_newlines is true as on Windows.
1 parent 0b4591e commit b3f194d

4 files changed

Lines changed: 40 additions & 5 deletions

File tree

Doc/library/subprocess.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -537,9 +537,10 @@ Instances of the :class:`Popen` class have the following methods:
537537
.. method:: Popen.communicate(input=None)
538538

539539
Interact with process: Send data to stdin. Read data from stdout and stderr,
540-
until end-of-file is reached. Wait for process to terminate. The optional
541-
*input* argument should be a byte string to be sent to the child process, or
542-
``None``, if no data should be sent to the child.
540+
until end-of-file is reached. Wait for process to terminate. The optional
541+
*input* argument should be data to be sent to the child process, or
542+
``None``, if no data should be sent to the child. The type of *input*
543+
must be bytes or, if *universal_newlines* was ``True``, a string.
543544

544545
:meth:`communicate` returns a tuple ``(stdoutdata, stderrdata)``.
545546

Lib/subprocess.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1519,6 +1519,8 @@ def close_unregister_and_remove(fd):
15191519
fd2output[self.stderr.fileno()] = stderr = []
15201520

15211521
input_offset = 0
1522+
if self.universal_newlines and isinstance(input, str):
1523+
input = input.encode(self.stdin.encoding)
15221524
while fd2file:
15231525
try:
15241526
ready = poller.poll()
@@ -1571,6 +1573,8 @@ def _communicate_with_select(self, input):
15711573
stderr = []
15721574

15731575
input_offset = 0
1576+
if self.universal_newlines and isinstance(input, str):
1577+
input = input.encode(self.stdin.encoding)
15741578
while read_set or write_set:
15751579
try:
15761580
rlist, wlist, xlist = select.select(read_set, write_set, [])

Lib/test/test_subprocess.py

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -608,8 +608,6 @@ def test_universal_newlines_communicate(self):
608608
universal_newlines=1)
609609
self.addCleanup(p.stdout.close)
610610
self.addCleanup(p.stderr.close)
611-
# BUG: can't give a non-empty stdin because it breaks both the
612-
# select- and poll-based communicate() implementations.
613611
(stdout, stderr) = p.communicate()
614612
self.assertEqual(stdout,
615613
"line2\nline4\nline5\nline6\nline7\nline8")
@@ -640,6 +638,35 @@ def test_universal_newlines_communicate_input_none(self):
640638
p.communicate()
641639
self.assertEqual(p.returncode, 0)
642640

641+
def test_universal_newlines_communicate_stdin_stdout_stderr(self):
642+
# universal newlines through communicate(), with stdin, stdout, stderr
643+
p = subprocess.Popen([sys.executable, "-c",
644+
'import sys,os;' + SETBINARY + '''\nif True:
645+
s = sys.stdin.buffer.readline()
646+
sys.stdout.buffer.write(s)
647+
sys.stdout.buffer.write(b"line2\\r")
648+
sys.stderr.buffer.write(b"eline2\\n")
649+
s = sys.stdin.buffer.read()
650+
sys.stdout.buffer.write(s)
651+
sys.stdout.buffer.write(b"line4\\n")
652+
sys.stdout.buffer.write(b"line5\\r\\n")
653+
sys.stderr.buffer.write(b"eline6\\r")
654+
sys.stderr.buffer.write(b"eline7\\r\\nz")
655+
'''],
656+
stdin=subprocess.PIPE,
657+
stderr=subprocess.PIPE,
658+
stdout=subprocess.PIPE,
659+
universal_newlines=True)
660+
self.addCleanup(p.stdout.close)
661+
self.addCleanup(p.stderr.close)
662+
(stdout, stderr) = p.communicate("line1\nline3\n")
663+
self.assertEqual(p.returncode, 0)
664+
self.assertEqual("line1\nline2\nline3\nline4\nline5\n", stdout)
665+
# Python debug build push something like "[42442 refs]\n"
666+
# to stderr at exit of subprocess.
667+
# Don't use assertStderrEqual because it strips CR and LF from output.
668+
self.assertTrue(stderr.startswith("eline2\neline6\neline7\n"))
669+
643670
def test_universal_newlines_communicate_encodings(self):
644671
# Check that universal newlines mode works for various encodings,
645672
# in particular for encodings in the UTF-16 and UTF-32 families.

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,9 @@ Core and Builtins
212212
Library
213213
-------
214214

215+
- Issue #16903: Popen.communicate() on Unix now accepts strings when
216+
universal_newlines is true as on Windows.
217+
215218
- Issue #6083: Fix multiple segmentation faults occured when PyArg_ParseTuple
216219
parses nested mutating sequence.
217220

0 commit comments

Comments
 (0)