开发者

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)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜