首页 文章

Python子进程丢失了程序的stdout的10%

提问于
浏览
2

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

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

不幸的是,当我使用communication [0]调用subprocess.popen2或subprocess.Popen时,当我使用subprocess.PIPE分配给stdout AND时,当我使用文件描述符时,我输掉了大约10%的输出数据(从开放的返回)分配给stdout .

子进程中的文档非常明确,如果您尝试捕获子进程的所有输出,则使用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
...

2 回答

  • 2

    我在 stdout 上使用了 subprocess ,输出量大得多,但很难得出's the root cause from what you'显示的内容 . 我会检查以下内容:

    由于 p.wait() 不适合你 . 可能是这样的情况,当你阅读_642582_时,你的java程序仍然忙于打印最后10% . 首先获得 p.wait()

    • 在你阅读 PIPE 之前插入一个足够大的等待(比如说30秒),你的10%出现了吗?

    • p.wait() 不会阻止你的java程序是值得怀疑的 . 你的java程序是否进一步对其他程序进行子处理?

    • 检查 p.wait() 的返回值 . 您的java程序是否正常终止?

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

    • 您在java程序中使用哪些函数打印到 stdout ?是倾向于还是忽视 IOException

    • 您是否正确刷新了流?当你的java程序终止时,最后10%可能在你的缓冲区中没有适当的刷新 .

  • 2

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

    out.py

    import sys
    
    for i in xrange(5000):
        print "%d\n" % i
    
    sys.exit(0)
    

    test.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正在做它的工作 .

相关问题