why does python.subprocess hang after proc.communicate()?
communicate()
reads data from stdout and stderr until end-of-file is reached. - It waits until your program quits.
From the docs for communicate
:
Interact with process: Send data to stdin. Read data from stdout and stderr, until end-of-file is reached. Wait for process to terminate.
So after communicate()
runs, the process has been terminated.
If you want to write and read without waiting for the process to stop:
Don't ever use
shell=True
- it needlessy invokes a shell to in turn call your program, so there will be another process between you and your program. That has lots of unpleasant side-effects. The default isshell=False
so you should stick with that. Change yourPopen
line to:p = subprocess.Popen(["./AO_FelixStrategy_UnitTest", "--bats", "31441", "--chix", "12467", "--enxutp", "31884", "--turq", "26372", "--symbol", "SOGN", "--target_date", '2009-Oct-16'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
Use
p.stdin.write
to write to the process. Usep.stdout.read
to read from it.- Calling
p.stdout.read
if there's nothing to read will block. Callingp.stdin.write
if the write buffer is full will block. So you have to make sure you have something to read/write - you do that on unix OS by usingselect
. On windows you unfortunately must resort to threads. At least that is whatPopen.communicate
does internally. - If you didn't write
AO_FelixStrategy_UnitTest
then you have possible additional problems:- It could be reading from somewhere else, not standard input. Some programs read directly from the terminal, others use some OS API to read. That means data written to stdin won't go to the program. This is often true for password prompts.
- Remember that you have to account for
AO_FelixStrategy_UnitTest
buffers. By default standard C PIPE communication is buffered so you may not see any output until after you've closed the input side (by doingp.stdin.close()
. UnlessAO_FelixStrategy_UnitTest
flushes the output periodically.
Here's some example code, based on what you describe. It could work depending on how AO_FelixStrategy_UnitTest
was developed:
p = subprocess.Popen(["./AO_FelixStrategy_UnitTest",
"--bats", "31441", "--chix", "12467",
"--enxutp", "31884", "--turq", "26372",
"--symbol", "SOGN", "--target_date", '2009-Oct-16'],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE)
output = p.communicate('S\nL\n')[0]
print output