From: Antoine Pitrou Date: Sat, 19 Mar 2011 16:06:22 +0000 (+0100) Subject: Issue #11459: A `bufsize` value of 0 in subprocess.Popen() really creates X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1679f4daa1b324bba87d952bc7da2c3e37f315fd;p=python Issue #11459: A `bufsize` value of 0 in subprocess.Popen() really creates unbuffered pipes, such that select() works properly on them. --- 1679f4daa1b324bba87d952bc7da2c3e37f315fd diff --cc Lib/platform.py index fb65b4ba34,abe917a4d5..75bc5f3b97 --- a/Lib/platform.py +++ b/Lib/platform.py @@@ -357,7 -357,61 +357,7 @@@ def dist(distname='',version='',id='' supported_dists=supported_dists, full_distribution_name=0) - def popen(cmd, mode='r', bufsize=None): -class _popen: - - """ Fairly portable (alternative) popen implementation. - - This is mostly needed in case os.popen() is not available, or - doesn't work as advertised, e.g. in Win9X GUI programs like - PythonWin or IDLE. - - Writing to the pipe is currently not supported. - - """ - tmpfile = '' - pipe = None - bufsize = None - mode = 'r' - - def __init__(self,cmd,mode='r',bufsize=None): - - if mode != 'r': - raise ValueError('popen()-emulation only supports read mode') - import tempfile - self.tmpfile = tmpfile = tempfile.mktemp() - os.system(cmd + ' > %s' % tmpfile) - self.pipe = open(tmpfile,'rb') - self.bufsize = bufsize - self.mode = mode - - def read(self): - - return self.pipe.read() - - def readlines(self): - - if self.bufsize is not None: - return self.pipe.readlines() - - def close(self, - - remove=os.unlink,error=os.error): - - if self.pipe: - rc = self.pipe.close() - else: - rc = 255 - if self.tmpfile: - try: - remove(self.tmpfile) - except error: - pass - return rc - - # Alias - __del__ = close - + def popen(cmd, mode='r', bufsize=-1): """ Portable popen() interface. """ diff --cc Lib/test/test_subprocess.py index 2dde245817,01e670ef72..6523c8a97e --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@@ -1313,8 -1214,24 +1313,24 @@@ class POSIXProcessTestCase(BaseTestCase stdout, stderr = p.communicate() self.assertEqual(0, p.returncode, "sigchild_ignore.py exited" " non-zero with this error:\n%s" % - stderr.decode('utf8')) + stderr.decode('utf-8')) + def test_select_unbuffered(self): + # Issue #11459: bufsize=0 should really set the pipes as + # unbuffered (and therefore let select() work properly). + select = support.import_module("select") + p = subprocess.Popen([sys.executable, "-c", + 'import sys;' + 'sys.stdout.write("apple")'], + stdout=subprocess.PIPE, + bufsize=0) + f = p.stdout + try: + self.assertEqual(f.read(4), b"appl") + self.assertIn(f, select.select([f], [], [], 0.0)[0]) + finally: + p.wait() + @unittest.skipUnless(mswindows, "Windows specific tests") class Win32ProcessTestCase(BaseTestCase):