当子进程崩溃或超时时,如何在子进程上获取stdout和stderr。Popen

问题描述 投票:0回答:1

当进程崩溃或超时时,我找不到从 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
python subprocess popen
1个回答
0
投票

在超时并调用

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,该过程似乎仍然运行完成。

© www.soinside.com 2019 - 2024. All rights reserved.