子进程冻结了popen()。stdout.read

时间:2013-06-19 18:16:32

标签: c++ python subprocess ipc cout

我有这个问题困扰我一段时间了,我似乎无法找到它的解决方案,我一直在使用subprocess.Popen()访问一个C ++应用程序,为我做了一些繁重的计算,但它继续冻结在Popen()。stdout.read(); 这是python代码:

process = subprocess.Popen(['/path/to/my/executable'], shell=False, 
stdout=subprocess.PIPE, stdin=subprocess.PIPE)
process.stdin.write("Some String")
print process.stdout.read()#It freezes here

这是c ++代码:

int main(int argc, char** argv) {
    ...Prep work...
    while (1) {
        string input;
        cin>>input;
    ...Some Work ...
        cout<< response;
    }
}

c ++代码在shell中完美运行,但我无法弄清楚为什么它会在python上冻结

2 个答案:

答案 0 :(得分:3)

改为使用communicate()

import subprocess
process = subprocess.Popen(['app'], shell=False,
                           stdout=subprocess.PIPE,
                           stdin=subprocess.PIPE)
out, err = process.communicate("Some String")
print out

另外,请确保在某个时候结束C ++过程。例如,当您到达输入流的末尾时:

#include <string>
#include <iostream>
using namespace std;

int main(int argc, char** argv) {
    //...Prep work...
    while (cin) {  // <-- Will eventually reach the end of the input stream
        string input;
        cin >> input;
        //...Some Work ...
        string response = input;
        cout << response;
    }
}

在python的文档中有一个警告: http://docs.python.org/2/library/subprocess.html#subprocess.Popen.stdin(正上方)

它解释了当您写入外部应用程序时,数据可能会被放入队列中。此外,您的外部应用程序的输出也可能会被放入队列中。 communic()将&#34; flush&#34;您要发送到外部应用程序的内容,并等到应用程序终止。

使用communicate()将获得整个外部应用程序在内存中的输出。如果它不实用(例如巨大的输出),则可以使用stdin和stdout对象进行写入或读取。你不需要照顾死锁&#34;:

import subprocess

process = subprocess.Popen(['app'], shell=False,
                           stdout=subprocess.PIPE,
                           stdin=subprocess.PIPE)
process.stdin.write("Some String")
process.stdin.close()  # <-- Makes sure the external app gets an EOF while
                       #     reading its input stream.
for line in process.stdout.readlines():
    print line

但即使采用这种技术,也要确保您提供给外部应用程序的输入足够小,以避免在写入时阻塞。

如果您的输入也很大,那么您必须确保您的读取和写入不会阻塞。使用线程很可能是一个不错的选择。

答案 1 :(得分:0)

通常我们需要非阻塞IO, 1)阅读所有回复,直到没有更多数据然后 2)向子进程发出一些东西, 重复1-2 使用线程也会有所帮助。