Python子进程模块:父子通信无法正常工作

时间:2011-07-08 08:20:08

标签: python subprocess popen

我正在尝试将以下代码作为子进程运行

#include<stdio.h>
int main()
{
    int a;
    printf("Hello\n");
    fprintf(stderr, "Hey\n");
    scanf("%d", &a);
    printf("%d\n", a);
    return 0;
}

这个脚本工作正常:写入stdin,从stdout和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()

但是这个脚本无法读取stdout的任何输出并在那里被阻止,即使C程序在要求任何输入之前打印到stdout。为什么我无法从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()

2 个答案:

答案 0 :(得分:2)

您首先需要flush流。这将确保所有数据实际写入流中。

#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;
}

默认情况下, stderr 是无缓冲的,这就是您不需要刷新它的原因。然而, stdout 是完全缓冲的,除非它指向一个终端,然后它进行行缓冲(即\n会自动触发刷新。

查看here,了解setbuf()和setvbuf()。

答案 1 :(得分:0)

我看不到像

这样的东西
stdout_data, stderr_data = p1.communicate()

代码

  

Popen.communicate(输入=无)

     

与流程交互:将数据发送到stdin。从stdout和stderr读取数据,直到达到文件结尾。等待进程终止。可选的输入参数应该是要发送到子进程的字符串,如果没有数据应该发送给子进程,则为None。

     

communic()返回一个元组(stdoutdata,stderrdata)。

     

请注意,如果要将数据发送到进程的stdin,则需要使用stdin = PIPE创建Popen对象。同样,要在结果元组中获取除None之外的任何内容,您还需要提供stdout = PIPE和/或stderr = PIPE。

     

注意读取的数据缓冲在内存中,因此如果数据量很大或无限制,请不要使用此方法。

请参阅docs.python.org

我保留在我的实用程序带中的函数包含使用子进程调用外部程序就是这个(修改以满足您的需要):

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

只需将命令放在变量中的cmd-line上,然后调用函数,例如:

cmd = r'git branch -r'
data = self.__run(cmd)