Python子进程损失10%的程序';斯道特

Python子进程损失10%的程序';斯道特,python,subprocess,Python,Subprocess,我有一个程序需要用python作为子进程调用。这个程序是用java编写的。是的,我知道 不管怎样,我需要捕获上述程序的所有输出 不幸的是,当我使用communicate[0]调用subprocess.popen2或subprocess.Popen时,当我使用分配给stdout的subprocess.PIPE和分配给stdout的文件描述符(打开时的返回)时,我会丢失大约10%的输出数据 subprocess中的文档非常明确,如果您试图捕获子进程的所有输出,那么使用subprocess.PIPE是

我有一个程序需要用python作为子进程调用。这个程序是用java编写的。是的,我知道

不管怎样,我需要捕获上述程序的所有输出

不幸的是,当我使用communicate[0]调用subprocess.popen2或subprocess.Popen时,当我使用分配给stdout的subprocess.PIPE和分配给stdout的文件描述符(打开时的返回)时,我会丢失大约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
...

我在
stdout
上使用了
subprocess
,但没有看到这样的问题。很难从你所展示的东西中得出什么是根本原因。我想检查一下:

因为
p.wait()
不适合你。可能是这样的,当您阅读
管道时,您的java程序仍然忙于打印最后的10%。获取
p.wait()
直接优先:

  • 在阅读
    管道之前,插入足够大的等待时间(比如30秒),是否显示10%的数据
  • p.wait()
    是否会阻塞java程序是值得怀疑的。您的java程序是否进一步子处理其他程序
  • 检查
    p.wait()
    的返回值。你的java程序正常终止了吗
如果问题不在并发模型中,请检查java程序中的打印是否正确:

  • 您在java程序中使用的打印到标准输出的函数是什么?它是否倾向于或忽略
    IOException
  • 你正确地冲洗了小溪吗?当java程序终止时,最后10%可能会在缓冲区中,而不会进行适当的刷新

我使用了
子流程,在
stdout
上有更大的输出,但没有看到这样的问题。很难从你所展示的东西中得出什么是根本原因。我想检查一下:

因为
p.wait()
不适合你。可能是这样的,当您阅读
管道时,您的java程序仍然忙于打印最后的10%。获取
p.wait()
直接优先:

  • 在阅读
    管道之前,插入足够大的等待时间(比如30秒),是否显示10%的数据
  • p.wait()
    是否会阻塞java程序是值得怀疑的。您的java程序是否进一步子处理其他程序
  • 检查
    p.wait()
    的返回值。你的java程序正常终止了吗
如果问题不在并发模型中,请检查java程序中的打印是否正确:

  • 您在java程序中使用的打印到标准输出的函数是什么?它是否倾向于或忽略
    IOException
  • 你正确地冲洗了小溪吗?当java程序终止时,最后10%可能会在缓冲区中,而不会进行适当的刷新

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

出局

test.py

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

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


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

它一定与您实际调用的进程有关。您可以通过使用另一个响应以下行的python脚本进行简单测试来验证这一点:

出局

test.py

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

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


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

是否有可能一些输出正在写入stderr?我们可以有一些Python代码吗?您缺少哪一个“10%”?这是开始还是结束?您希望得到什么样的输出?您确定您的java子进程本身没有分叉吗?这可能解释了为什么
wait()
调用似乎没有阻塞。更具体地说,使用
subprocess.PIPE
或为子进程的输出分配一个fd本质上与shell在执行文件输出重定向(操作系统的
dup2()
系统调用)时所做的事情完全相同。您可以放心地假设该部件正在工作。您可以尝试在命令末尾添加“`tee outputcopy
”;然后您可以检查
outputcopy`是否具有您期望的所有行。如果没有,可能是您的java程序工作不正常。是否有可能某些输出正在写入stderr?我们可以使用一些Python代码吗?您缺少哪一个“10%”?这是开始还是结束?您希望得到什么输出?您确定您的java子进程不是吗
import sys

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

sys.exit(0)
import subprocess

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

print output