Python从子进程中逐行捕获stdout
我已经阅读了许多与此相关的问题并学到了很多东西,但我仍然无法解决我的问题。我正在构建一个 wxPython 应用程序,它运行 c++ 可执行文件并实时显示该可执行文件的标准输出。为了使这项工作顺利进行,我遇到了一些奇怪的结果。这是我当前的设置/问题:
//test.cc (compiled as test.out with gcc 4.5.2)
#include <stdio.h>
int main()
{
FILE* fh = fopen("output.txt", "w");
for (int i = 0; i < 10000; i++)
{
printf("Outputting: %d\n", i);
fprintf(fh, "Outputting: %d\n", i);
}
fclose(fh);
return 0;
}
#wxPythonScript.py (running on 2.7 interpreter)
def run(self):
self.externalBinary = subprocess.Popen(['./test.out'], shell=False, stdout=subprocess.PIPE)
while not self.wantAbort:
line = self.externalBinary.stdout.readline()
wx.PostEvent(self.notifyWindow, Result_Event(line, Result_Event.EVT_STDOUT_ID))
print('Subprocess still running')
print('Subprocess aborted smoothly')
如果我运行上面的代码,子进程需要很长时间才能完成,即使它所要做的就是写出数据并退出。但是,如果我运行以下命令,它会很快完成:
#wxPythonScript.py (running on 2.7 interpreter)
def run(self):
outFile = open('output.txt', 'r+')
self.externalBinary = subprocess.Popen(['./test.out'], shell=False, stdout=outFile)
while not self.wantAbort:
#line = self.externalBinary.stdout.readline()
#wx.PostEvent(self.notifyWindow, Result_Event(line, Result_Event.EVT_STDOUT_ID))
print('Subprocess still running')
print('Subprocess aborted smoothly')
所以基本上,每当我将 stdout 从子进程重定向到 PIPE 时,它都会减慢/挂起,但如果我将其写入文件或根本不重定向它,那就没问题了。这是为什么?
I've read many of the questions related to this and learned a lot but I still haven't been able to solve my problem. I'm building a wxPython app that runs a c++ executable and displays the stdout from that executable in real time. I've run into several strange results trying to make this work. Here's my current setup/problem:
//test.cc (compiled as test.out with gcc 4.5.2)
#include <stdio.h>
int main()
{
FILE* fh = fopen("output.txt", "w");
for (int i = 0; i < 10000; i++)
{
printf("Outputting: %d\n", i);
fprintf(fh, "Outputting: %d\n", i);
}
fclose(fh);
return 0;
}
#wxPythonScript.py (running on 2.7 interpreter)
def run(self):
self.externalBinary = subprocess.Popen(['./test.out'], shell=False, stdout=subprocess.PIPE)
while not self.wantAbort:
line = self.externalBinary.stdout.readline()
wx.PostEvent(self.notifyWindow, Result_Event(line, Result_Event.EVT_STDOUT_ID))
print('Subprocess still running')
print('Subprocess aborted smoothly')
If I run the above code the subprocess takes a very long time to complete, even though all it has to do is write out the data and exit. However if I run the following it completes very quickly:
#wxPythonScript.py (running on 2.7 interpreter)
def run(self):
outFile = open('output.txt', 'r+')
self.externalBinary = subprocess.Popen(['./test.out'], shell=False, stdout=outFile)
while not self.wantAbort:
#line = self.externalBinary.stdout.readline()
#wx.PostEvent(self.notifyWindow, Result_Event(line, Result_Event.EVT_STDOUT_ID))
print('Subprocess still running')
print('Subprocess aborted smoothly')
So basically whenever I redirect stdout from the subprocess to a PIPE it slows down/hangs, but if I write it to a file or don't redirect it at all then it's fine. Why is that?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我只在 Windows 上测试过这个,但它可以在 2.6.6、2.7.2 和 3.2.1 中工作:
输出:
编辑:
readline() 将阻塞,直到程序的 stdout 缓冲区刷新,如果数据流刷新,这可能需要很长时间是间歇性的。如果您可以编辑源代码,一种选择是手动调用 fflush(stdout),或者您可以在程序开始时使用 setvbuf 禁用缓冲。例如:
还要考虑使用 unbuffer 或 stdbuf 修改现有程序的输出流。
I only tested this on Windows, but it works in 2.6.6, 2.7.2, and 3.2.1:
Output:
Edit:
readline() will block until the program's stdout buffer flushes, which may take a long time if the data stream is intermittent. If you can edit the source, one option is to manually call fflush(stdout), or you can instead disable buffering using setvbuf at the start of the program. For example:
Also look into using unbuffer or stdbuf to modify the output stream of an existing program.