4

这个问题困扰了我一段时间,我似乎找不到解决方案,我一直在使用 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 上冻结

4

2 回答 2

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(右上方)

它解释说,当您写入外部应用程序时,数据可能会放入队列中。此外,您的外部应用程序的输出也可能会放入队列中。communicate() 将“刷新”您发送到外部应用程序的内容并等到您的应用程序终止。

使用communicate()将在内存中获取整个外部应用程序的输出。如果它不实用(例如巨大的输出),那么您可以使用 stdin 和 stdout 对象进行写入或读取。您需要注意不要“死锁”:

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

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

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

于 2013-06-19T19:11:45.033 回答
0

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

于 2015-05-30T20:38:26.853 回答