【问题标题】:Python subprocess module: parent child communication not workingPython子进程模块:父子通信不起作用
【发布时间】:2011-10-01 02:19:43
【问题描述】:

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

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

这个脚本工作正常:写入标准输入,从标准输出和标准错误读取。

#!/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()

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

【问题讨论】:

    标签: python subprocess popen


    【解决方案1】:

    您需要先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()。

    【讨论】:

      【解决方案2】:

      我没有看到类似的东西

      stdout_data, stderr_data = p1.communicate()
      

      在你的代码中

      Popen.communicate(input=None)

      与进程交互:将数据发送到标准输入。从 stdout 和 stderr 读取数据,直到到达文件结尾。等待进程终止。可选的输入参数应该是一个要发送到子进程的字符串,或者 None,如果不应该向子进程发送数据。

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

      请注意,如果您想将数据发送到进程的标准输入,您需要使用标准输入=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 行中的变量中,然后调用函数,例如:

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

      【讨论】:

      • 我不认为他想要communicate() - 因为“等待进程终止。”这就是为什么 - 我认为 - p.wait() 在你的代码中是多余的,因为它本质上是做同样的事情。
      猜你喜欢
      • 2011-01-09
      • 2017-07-22
      • 1970-01-01
      • 2014-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-29
      • 1970-01-01
      相关资源
      最近更新 更多