我从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
的情况下实现相同的功能?
我可以让这个过程在后台默默运行,但我更喜欢一个允许它阻塞的解决方案,并且我可以捕获输出。
围绕这个障碍是否有解决方法?
提前致谢!