Python-使用Popen.communicate()不会像预期的那样捕获系统调用的stdout和stderr
我有一个Python脚本,它执行一个系统调用(该调用实际上是一个Python-使用Popen.communicate()不会像预期的那样捕获系统调用的stdout和stderr,python,subprocess,Python,Subprocess,我有一个Python脚本,它执行一个系统调用(该调用实际上是一个java程序)。 我正在使用Popen.communicate()尝试捕获stdout和stderr。但是,它只适用于一些Java应用程序(其中,我调用的所有Java应用程序在shell中直接执行时都会在屏幕上显示一些内容) 我使用的代码如下: # Perform the java call try: p = subprocess.Popen(args,
java
程序)。
我正在使用Popen.communicate()
尝试捕获stdout
和stderr
。但是,它只适用于一些Java
应用程序(其中,我调用的所有Java
应用程序在shell中直接执行时都会在屏幕上显示一些内容)
我使用的代码如下:
# 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)
,而在另一种情况下则是这样
有人对此有任何经验吗?我注意到的第一件事是,您正在读取进程stdout中的所有内容,然后尝试执行
通信
:您已经读取了管道中的所有内容,因此输出
结果来自p.communicate()
将始终为空
但这并不能解释为什么有时不调用sys.stdout.write
需要记住的一点是,在控制台(即,在命令窗口)中显示内容有多种方式。打印到进程标准输出流只是一种方式,这是您可以使用上述代码捕获的方式。如果我回想一下Java时代,有一些类型的
Console
类有时用于显示到控制台,这可能不使用stdout。此外,高级控制台显示库,例如curses
,通常不会写入标准输出,它们直接与控制台对象交互。我不知道如何或是否可以从这些类型的进程中捕获输出,但如果可能的话,它可能会非常特定于系统。感谢您的指点。我想我没有注意到输出
为空的原因是我真的只对stderr
感兴趣。但你确实帮我了解了一些这是怎么回事。不幸的是,关于如何从控制台
类获取输出的问题仍然悬而未决@布雷特:另一个问题是,您设置了stderr=PIPE
,但没有与stdout
同时读取。如果程序填充对应于子进程的操作系统管道缓冲区,则可能导致死锁stderr@J.F.Sebastian有趣。关于我应该如何处理这个问题,有什么建议吗?@Brett:你可以尝试pexpect
,pty
模块,例如,(如果程序直接写入终端,它会解决问题)。@Brett:如果你指的是如何同时读取stdout
和stderr
,那么1。设置stderr=STDOUT
如果不可接受,则设置2。使用threads、select.select、fctnl(使管道不阻塞)或iocp(在Windows上)