Reputation: 75615
I want to make a Python wrapper for another command-line program.
I want to read Python's stdin
as quickly as possible, filter and translate it, and then write it promptly to the child program's stdin
.
At the same time, I want to be reading as quickly as possible from the child program's stdout
and, after a bit of massaging, writing it promptly to Python's stdout
.
The Python subprocess module is full of warnings to use communicate()
to avoid deadlocks. However, communicate()
doesn't give me access to the child program's stdout
until the child has terminated.
Upvotes: 3
Views: 590
Reputation: 25409
I think you'll be fine (carefully) ignoring the warnings using Popen.stdin
, etc yourself. Just be sure to process the streams line-by-line and iterate through them on a fair schedule so not to fill up any buffers. A relatively simple (and inefficient) way of doing this in Python is using separate threads for the three streams. That's how Popen.communicate
does it internally. Check out its source code to see how.
Upvotes: 1
Reputation: 4926
Disclaimer: This solution likely requires that you have access to the source code of the process you are trying to call, but may be worth trying anyways. It depends on the called process periodically flushing its stdout
buffer which is not standard.
Say you have a process proc
created by subprocess.Popen
. proc
has attributes stdin
and stdout
. These attributes are simply file-like objects. So, in order to send information through stdin
you would call proc.stdin.write()
. To retrieve information from proc.stdout
you would call proc.stdout.readline()
to read an individual line.
A couple of caveats:
proc.stdin
via write()
you will need to end the input with a newline character. Without a newline character, your subprocess will hang until a newline is passed.proc.stdout
you will need to make sure that the command called by subprocess appropriately flushes its stdout buffer after each print statement and that each line ends with a newline. If the stdout buffer does not flush at appropriate times, your call to proc.stdout.readline()
will hang.Upvotes: 1