Python subprocess module: parent child communication not working
I'm trying to run the following code as a subprocess
#include<stdio.h>
int main()
{
int a;
printf("Hello\n");
fprintf(stderr, "Hey\n");
scanf("%d", &a);
printf("%d\n开发者_如何学C", a);
return 0;
}
This script works fine: write to stdin, read from stdout and from stderr.
#!/usr/bin/python
import subprocess
p1=subprocess.Popen("/mnt/test/a.out", stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)
p1.stdin.write('1\n')
print p1.stdout.readline()
print p1.stderr.readline()
print p1.stdout.readline()
But this script fails to read any output from stdout and gets blocked there even though the C program does print to stdout before demanding any input. Why is it that I'm unable to read anything from stdout?
#!/usr/bin/python
import subprocess
p1=subprocess.Popen("/mnt/test/a.out", stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)
print p1.stdout.readline()
p1.stdin.write('1\n')
print p1.stderr.readline()
print p1.stdout.readline()
You need to flush the stream first. This will make sure all data is actually written to the stream.
#include<stdio.h>
int main()
{
int a;
printf("Hello\n");
fprintf(stderr, "Hey\n");
fflush(stdout); // <--
scanf("%d", &a);
printf("%d\n", a);
return 0;
}
By default, stderr is unbuffered, which is why you don't need to flush it. stdout however is fully buffered, unless it points to a terminal, then it line-buffered (i.e. the \n
would automatically trigger flushing.
Have a look here, for setbuf() and setvbuf().
I don't see something like
stdout_data, stderr_data = p1.communicate()
in your code
Popen.communicate(input=None)
Interact with process: Send data to stdin. Read data from stdout and stderr, until end-of-file is reached. Wait for process to terminate. The optional input argument should be a string to be sent to the child process, or None, if no data should be sent to the child.
communicate() returns a tuple (stdoutdata, stderrdata).
Note that if you want to send data to the process’s stdin, you need to create the Popen object with stdin=PIPE. Similarly, to get anything other than None in the result tuple, you need to give stdout=PIPE and/or stderr=PIPE too.
Note The data read is buffered in memory, so do not use this method if the data size is large or unlimited.
See docs.python.org
A function I keep in my utility-belt to wrap calling an external program using subprocess is this (modify to suit your needs):
def __run(self, cmd):
"""wrapper, makes it easy to call an external program.
return the result as a newline-separated list
"""
args = shlex.split(cmd)
try:
p = subprocess.Popen(args, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
retdata = p.communicate()[0]
p.wait()
except OSError, e:
print >>sys.stderr, "Execution failed:", e
return (p.returncode, retdata.split('\n'))
Just place your command as you would write it on the cmd-line in a variable an call the function e.g.:
cmd = r'git branch -r'
data = self.__run(cmd)
精彩评论