当进程崩溃或超时时,我找不到从 subprocess.Popen 获取 stdout 和 stderr 的方法。我添加了 try-exception 子句来捕获这些情况,但在异常处理程序上,因为 Popen 函数失败,我没有 stdout 和 stderr 变量,并且异常对象 'e' 尽管有 e.output 和 e.stderr他们都没有…… 我还尝试从 proc 变量中提取 stdout 和 stderr,但找不到正确的方法(如果可能的话)。 请参阅下面的示例代码。
proc = subprocess.Popen(cmd_full, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=True, env=env)
try:
stdout, stderr = proc.communicate(timeout=TIMEOUT_SEC)
return_code = proc.returncode
stdout_str = stdout
stderr_str = stderr
except subprocess.TimeoutExpired as e:
proc.kill()
#kill_proc() # I use this instead of the previous line because proc.kill() doesn't kill my process for some reason...
stdout_str = e.output
stderr_str = e.stderr
except subprocess.CalledProcessError as e:
stdout = e.output
stderr = e.stderr
except Exception as e:
stdout = e.output
stderr = e.stderr
在超时并调用
proc.kill
(无论 proc_kill()
是什么,我们都会从看到该代码中受益)之后,您应该根据文档再次调用方法 communicate
来检索输出。这是否适用于proc_kill
,出于明显的原因,我不能说。
为了演示以下文件 test.py 检查是否已指定命令行参数。如果没有,它会调用
subprocess.Popen
指定原始程序,但这次传递一个参数。当使用参数调用程序时(应该是休眠的秒数),它会打印出一些消息并休眠指定的时间,强制超时:
import sys
def main():
import subprocess
import os
cmd_full = f'{sys.argv[0]} 3.0' # python test.py 3.0
cwd = '.' # Current directory
TIMEOUT_SEC = 1
env = os.environ
proc = subprocess.Popen(cmd_full, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=True, env=env)
try:
stdout, stderr = proc.wait(timeout=TIMEOUT_SEC)
except subprocess.TimeoutExpired as e:
print('Timeout occurred.')
proc.kill() # Or kill_proc() (whatever that might be???)
stdout, stderr = proc.communicate() # Reissue call
... # etc.
print('stdout output:')
print(stdout, end='')
print()
print('stderr output:')
print(stderr, end='')
return_code = proc.returncode
print()
print('return code =', return_code)
if __name__ == '__main__':
import sys
import time
if len(sys.argv) == 1:
# No command line argument so create subprocess:
main()
else:
# Invoked by subprocess.Popen call:
sleep_time = float(sys.argv[1])
print('starting')
print(f'Sleeping for {sleep_time} seconds ...')
time.sleep(sleep_time)
print('ending')
打印:
Timeout occurred.
stdout output:
starting
Sleeping for 3.0 seconds ...
ending
stderr output:
return code = 1
可以看出,即使调用了
proc.kill()
并且最终返回码为1,该过程似乎仍然运行完成。