子进程冻结 popen().stdout.read
Posted
技术标签:
【中文标题】子进程冻结 popen().stdout.read【英文标题】:Subprocess freezes popen().stdout.read 【发布时间】:2013-06-19 18:16:32 【问题描述】:这个问题困扰了我一段时间,我似乎找不到解决方案,我一直在使用 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 上冻结
【问题讨论】:
因为Python脚本等待子进程结束? 我可以在不等待进程结束的情况下读取 cout 吗? 如果process.stdin
被缓冲,您的写入可能不会立即对 C++ 程序可见。同样,如果 process.stdout
被缓冲,C++ 写入可能不会立即对您的 Python 程序可见。
您应该能够将长度参数传递给read()
,否则您将等待一个EOF,在子流程完成之前您可能不会有。
感谢您的回复,但我尝试添加长度参数但仍然没有输出
【参考方案1】:
改用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
但即使使用这种技术,也要确保您提供给外部应用程序的输入足够小,以避免在写入时阻塞。
如果您的输入也很大,则必须确保您的读写没有阻塞。那么使用线程很可能是一个不错的选择。
【讨论】:
感谢您的回复@Teebrin,我试过了,现在我得到了这个错误,err = process.communicate(command) File "/usr/lib/python2.7/subprocess. py”,第 806 行,在通信中返回 self._communicate(input) 文件“/usr/lib/python2.7/subprocess.py”,第 1382 行,在 _communicate 标准输出中,stderr = self._communicate_with_poll(input) 文件“/usr /lib/python2.7/subprocess.py",第 1456 行,在 _communicate_with_poll 数据 = os.read(fd, 4096) MemoryError 您的外部应用程序可能正在输出大量数据。我编辑了我的答案,以举例说明如何阅读大量输出。事实上,它更像你的原始代码。【参考方案2】:通常我们需要非阻塞 IO, 1)读取所有回复,直到没有更多数据,然后 2)向子进程发出一些东西, 重复 1-2 使用线程也会有所帮助。
【讨论】:
以上是关于子进程冻结 popen().stdout.read的主要内容,如果未能解决你的问题,请参考以下文章