Python - 使用Popen.communicate()无法按预期捕获系统调用的stdout和stderr
我有一个Python脚本,它会执行一个系统调用(这个调用实际上是一个java
程序)。我正在使用Popen.communicate()
来尝试捕获stdout
(标准输出)和stderr
(错误输出)。不过,这个方法只对某些Java
应用程序有效(我调用的所有java
应用程序在直接在命令行中执行时,都会在屏幕上显示一些内容)。
我使用的代码如下:
# Perform the java call
try:
p = subprocess.Popen(args,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
except OSError as e:
error_msg = ' Error reading file while executing system command: {0}'.format(e.message)
except ValueError as e:
error_msg = ' Error in arugments while executing system command: {0}'.format(e.message)
else:
# Display the results in real time
for line in iter(p.stdout.readline, ''):
sys.stdout.write(line)
# Grab the stdout and stderr from the process.
output, err = p.communicate()
finally:
# Check to see if an internal error occurred. If not, flip the flag
if not err and not error_msg:
java_completed = True
else:
java_completed = False
在某些情况下,sys.stdout.write(line)
这一行从来没有被调用,而在其他情况下又会被调用。
有没有人有过类似的经验?
1 个回答
1
我首先注意到的是,你在从进程的标准输出(stdout)中读取所有内容,然后再尝试使用communicate
:你已经从管道中读取了所有内容,所以p.communicate()
的output
结果总是会是空的。
不过,这并不能解释为什么有时候sys.stdout.write
没有被调用。
需要记住的一点是,在控制台(也就是命令窗口)中显示内容有很多种方式。打印到进程的标准输出流只是其中一种,而这也是你能用上面代码捕获到的方式。如果我没记错的话,在Java中有一种Console
类,有时用来在控制台上显示内容,这可能并不使用标准输出。此外,一些高级的控制台显示库,比如curses
,通常不会写入标准输出,而是直接与控制台对象进行交互。我不知道你是否能捕获这些类型进程的输出,但如果可以的话,可能会非常依赖于具体的系统。