【问题标题】:Python 3 subprocess module - return console output after timeout hitPython 3 子进程模块 - 超时命中后返回控制台输出
【发布时间】:2021-03-10 23:46:39
【问题描述】:

我有下面的代码,它启动一个可执行文件,并在它完成执行后等待来自 shell 的响应。我有 60 秒的超时设置。如果可执行文件在 60 秒内完成工作,则变量 streamdata 是一个字符串,其中包含您以交互方式运行可执行文件时将打印到控制台屏幕的内容。

但是,如果达到超时截止,streamdata 的值似乎只是一个空白的二进制字符串。我该如何修改,以便在超时杀死 .exe 后仍然获得 STDOUT?

startupinfo = None
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
            
process = subprocess.Popen([<parameters>], stdout=subprocess.PIPE, startupinfo=startupinfo)
process2 = process.pid
streamdata = process.communicate(timeout=60)[0]
streamdata2 = streamdata.decode(errors='replace')
rc = process.returncode

【问题讨论】:

    标签: python python-3.x subprocess


    【解决方案1】:

    让子进程将stdout 重定向到一个文件(或其他东西),然后读取它。 例如:

    import subprocess
    import os
    program_path="E:/Project2.exe"
    file_path="E:/1.txt"
    if os.path.exists(file_path):
        os.remove(file_path)
    
    startupinfo = None
    startupinfo = subprocess.STARTUPINFO()
    startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
    with open(file_path,'w') as f:
        process = subprocess.Popen([program_path],stdout=f, startupinfo = startupinfo)
    process2 = process.pid
    try:
        streamdata = process.communicate(timeout=2)[0]
    except Exception:
        print("Time Out!")
        with open(file_path, 'r') as f:
            print(f.readlines())
        process.kill()
    

    输出:

    Time Out!
    ['1\n', '1\n', '1\n', '1\n', '1\n', '1\n', '1\n', '1\n', '1\n', '1\n', '1\n', '1\n', '1\n', '1\n', '1\n', '1\n', '1\n', '1\n', '1\n', '1\n']
    

    如果您想获得尽可能多的输出,请在子进程中更频繁地刷新stdout

    如果你只需要在控制台看到输出:

    startupinfo = None
    startupinfo = subprocess.STARTUPINFO()
    startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
                
    process = subprocess.Popen([<parameters>],startupinfo=startupinfo)#<-here is the difference
    process2 = process.pid
    streamdata = process.communicate(timeout=60)[0]
    streamdata2 = streamdata.decode(errors='replace')
    rc = process.returncode
    

    【讨论】:

    • 嗨 - 欢迎。如果没有外部文件,这不能实现吗?只需直接打印到 python 控制台。
    • @gdogg371 更简单,只需删除代码中的stdout=subprocess.PIPE 部分即可。或使用stdout=sys.stdout
    • 你能编辑你的答案,让我明白你的意思吗?我不确定我是否完全理解...
    • 您的第二个代码块与我现在的代码完全相同...问题不在于这根本不起作用...它确实有效,只要可执行文件完成它的动作在子进程抛出超时之前的分配时间内。我不知道如何实现的是如何在超时之前获取标准输出。 process.communicate() 关闭标准输入、标准输出和标准错误...
    • @gdogg371: 不,你的代码有点不同。第二个代码块让子进程在你的控制台中输出所有内容。如果你仍然什么也没看到,就像我说的,你应该刷新stdout/关闭子进程的缓冲区。
    【解决方案2】:

    Op 的回答无效。然而,经过一个下午的折腾,我终于得到了下面的工作。在 SO 上真的找不到任何可比较的答案,但是我的解决方案几乎完全基于子流程文档中给出的示例,因此吸取的教训是不要总是依赖这里并在发布之前咨询文档!

    try:
                
        startupinfo = None
        startupinfo = subprocess.STARTUPINFO()
        startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
            
        process = subprocess.Popen([<parameters>], stdout=subprocess.PIPE, stderr=subprocess.PIPE, startupinfo=startupinfo)
        process2 = process.pid
    
        outs, errs = process.communicate(timeout=5)
        print(outs)
    
    except subprocess.TimeoutExpired:
    
        process.kill()
        outs, errs = process.communicate(timeout=6)
        print(outs)
    

    【讨论】:

      猜你喜欢
      • 2017-05-29
      • 2014-03-13
      • 2012-05-21
      • 2018-05-28
      • 2017-02-07
      • 2018-02-16
      • 2021-03-09
      • 2021-05-06
      • 2019-08-26
      相关资源
      最近更新 更多