3

我有一个程序需要被称为 python 的子进程。该程序是用java编写的。是的,我知道...

无论如何,我需要捕获所述程序的所有输出。

不幸的是,当我使用通信 [0] 调用 subprocess.popen2 或 subprocess.Popen 时,当我使用分配给 stdout 的 subprocess.PIPE 和使用文件描述符时,我丢失了大约 10% 的输出数据(从打开的返回)分配给标准输出。

subprocess 中的文档非常明确,如果您尝试捕获子进程的所有输出,则使用 subprocess.PIPE 是不稳定的。

我目前正在使用 pexpect 将输出转储到 tmp 文件中,但由于显而易见的原因,这需要永远。

我想将所有数据保存在内存中以避免磁盘写入。

欢迎任何建议!谢谢!

import subprocess

cmd = 'java -Xmx2048m -cp "/home/usr/javalibs/class:/home/usr/javalibs/libs/dependency.jar" --data data --input input" 

# doesn't get all the data
#
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
output = p.communicate()[0]

OR
# doesn't get all the data
#
fd = open("outputfile",'w')
p = subprocess.Popen(cmd, stdout=fd, shell=True)
p.communicate()
fd.close() # tried to use fd.flush() too.

# also tried
# p.wait() instead of p.communicate(), but wait doesn't really wait for the java program to finish running - it doesn't block

OR
# also fails to get all the data
#
import popen2
(rstdout, rstdin) = popen2.popen2(cmd)

预期输出是一系列 ascii 行(几千行)。这些行包含一个数字和一个行尾字符

0\n
1\n
4\n
0\n
...
4

2 回答 2

2

我曾经使用subprocess过更大的输出,stdout但没有看到这样的问题。很难从您所展示的内容中得出根本原因是什么。我会检查以下内容:

因为p.wait()没有为你工作。可能是这样的情况,当您阅读您PIPE的 java 程序时,仍然忙于打印最后 10%。先说正事p.wait()

  • 在阅读之前插入足够长的等待时间(比如 30 秒),PIPE你的 10% 会出现吗?
  • p.wait()是否会阻止您的 java 程序是值得怀疑的。您的 java 程序是否进一步子处理其他程序?
  • 检查的返回值p.wait()。你的java程序正常终止了吗?

如果问题不在于您的并发模型,请检查您是否在 java 程序中正确打印:

  • 你在你的java程序中使用了什么函数来打印stdout?它是倾向于还是忽略IOException
  • 您是否正确刷新了流?当您的 java 程序终止时,最后 10% 可能在您的缓冲区中而没有适当的刷新。
于 2012-05-21T18:29:10.927 回答
2

它必须与您实际调用的过程相关。您可以通过使用另一个回显行的 python 脚本进行简单测试来验证这一点:

出.py

import sys

for i in xrange(5000):
    print "%d\n" % i

sys.exit(0)

测试.py

import subprocess

cmd = "python out.py"
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
output = p.communicate()[0]

print output

因此,您可以验证问题不是数据的大小,而是与您正在调用的进程的通信。

您还应该确认您正在运行的 python 版本,因为我已经阅读了有关 Popen 内部缓冲区的过去问题(但使用您建议的单独文件句柄通常为我修复)。

如果子进程调用无限期挂起,这将是一个缓冲区问题。但如果这个过程正在完成,只是缺少线条,那么 Popen 就在做它的工作。

于 2012-05-21T19:06:17.853 回答