communic()导致子进程失败 - 为什么?

时间:2015-11-25 13:21:07

标签: java python python-2.7 subprocess

我从python调用java应用程序就像这样:

proc = subprocess.Popen(
    ["java", "-jar", "application.jar", "-o", "/path/to/outfile", "/path/to/infile"])

当子进程在上面静默运行时,如上所述,这可以按预期工作(应用程序生成文件,包含它们应该包含的内容)。

然而,我希望一个过程被阻止,而另一个过程要抓住它的输出。

因此采用以下方法:

try:
    proc = subprocess.Popen(
        ["java", "-jar", "application.jar", "-o", "/path/to/outfile", "/path/to/infile"],
        stderr=subprocess.PIPE,
        stdout=subprocess.PIPE)
    pstdout, pstderr = proc.communicate()
    if pstderr:
        raise Exception("Some exception")
    else:
        print "done"
except:
    print "FAILED"

此失败(以前成功生成的文件为0字节) - 即使Popen args完全相同。

没有try ... except和条件

proc = subprocess.Popen(
    ["java", "-jar", "application.jar", "-o", "/path/to/outfile", "/path/to/infile"],
    stderr=subprocess.PIPE,
    stdout=subprocess.PIPE)
print proc.communicate() #prints java exception

它仍然失败。
print proc.communicate()打印的例外情况是Java StringIndexOutOfBoundsException,以防它有所不同 删除对communicate()的调用会使其再次按计划执行:

proc = subprocess.Popen(
    ["java", "-jar", "application.jar", "-o", "/path/to/outfile", "/path/to/infile"],
    stderr=subprocess.PIPE,
    stdout=subprocess.PIPE) # runs just fine

更多信息(编辑)
有问题的Java应用程序是YUI Compressor,Yahoo的CSS和JS压缩工具。

如果它确实有助于消除光线,那么从java到pithon的完整堆栈跟踪将被包含在上面第二个代码块中的psterr中:

Exception in thread "main" java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at com.yahoo.platform.yui.compressor.Bootstrap.main(Bootstrap.java:21)
Caused by: java.lang.StringIndexOutOfBoundsException: String index out of range: -860
    at java.lang.AbstractStringBuilder.substring(AbstractStringBuilder.java:908)
    at java.lang.StringBuffer.substring(StringBuffer.java:482)
    at com.yahoo.platform.yui.compressor.CssCompressor.compress(CssCompressor.java:126)
    at com.yahoo.platform.yui.compressor.YUICompressor.main(YUICompressor.java:211)
    ... 5 more

TL; DR
虽然我只是为了捕获输出而调用communicate(),但它也会以某种方式向子进程发送垃圾,使其失败。
为什么会这样?

我认为这是因为java应用程序仍然从stdin读取而communicate()在其间发送EOF。 如何在不发送EOF的情况下实现相同的功能?

我可以让这个过程在后台默默运行,但我更喜欢一个允许它阻塞的解决方案,并且我可以捕获输出。
围绕这个障碍是否有解决方法?

提前致谢!

0 个答案:

没有答案