2

The code from the accepted answer to Keep a subprocess alive and keep giving it commands? Python isn't working in python 3.6 (it just hangs). Is there a way to fix it?

from subprocess import Popen, PIPE

# Run "cat", which is a simple Linux program that prints it's input.
process = Popen(['/bin/cat'], stdin=PIPE, stdout=PIPE, encoding='utf-8', universal_newlines=True)
process.stdin.write('Hello\n')
print(repr(process.stdout.readline())) # Should print 'Hello\n'
process.stdin.write(b'World\n')
print(repr(process.stdout.readline())) # Should print 'World\n'

# "cat" will exit when you close stdin.  (Not all programs do this!)
process.stdin.close()
print('Waiting for cat to exit')
process.wait()
print('cat finished with return code %d' % process.returncode)
maxymoo
  • 35,286
  • 11
  • 92
  • 119

3 Answers3

4

As per @DanielPryden's suggestion, you need to explicitly flush the stdin:

from subprocess import Popen, PIPE

# Run "cat", which is a simple Linux program that prints it's input.
process = Popen(['/bin/cat'], stdin=PIPE, stdout=PIPE)
process.stdin.write(b'Hello\n')
process.stdin.flush()
print(repr(process.stdout.readline())) # Should print 'Hello\n'
process.stdin.write(b'World\n')
process.stdin.flush()
print(repr(process.stdout.readline())) # Should print 'World\n'

# "cat" will exit when you close stdin.  (Not all programs do this!)
process.stdin.close()
print('Waiting for cat to exit')
process.wait()
print('cat finished with return code %d' % process.returncode)
maxymoo
  • 35,286
  • 11
  • 92
  • 119
1

Between cat and your program is a buffer, most likely in the libc stdio implementation on the Python side. You need to flush this buffer to ensure cat has seen the bytes you wrote before putting your process to sleep waiting for cat to write some bytes back.

You can do this explicitly with a process.stdin.flush() call, or you can do it implicitly by disabling the buffer. I think the explicit form is probably better here: it's simple and clearly correct.

Daniel Pryden
  • 59,486
  • 16
  • 97
  • 135
0

In Python 3.6 (and in other versions as far as I know), process.stdin.write takes a byte object, not a string.

process.stdin.write(b'Hello\n')

EDIT: This answer was invalidated after the edit to the question. (It added an encoding to the Popen constructor.)

AAM111
  • 1,178
  • 3
  • 19
  • 39