【问题标题】:Live-output / stream from Python subprocess来自 Python 子进程的实时输出/流
【发布时间】:2019-06-03 02:55:27
【问题描述】:

我正在使用 Python,它的子进程库使用 strace 检查调用的输出,涉及以下问题:

subprocess.check_output(["strace", str(processname)]) 

但是,这只会在调用的子进程已经完成之后给我输出,这对我的用例来说是非常有限的。

我需要进程的一种“流”或实时输出,因此我需要在进程仍在运行时读取输出,而不是仅在进程完成后读取。

有没有一种方便的方法可以使用子流程库来实现这一点? 我正在考虑每 x 秒进行一次民意调查,但没有在文档中找到有关如何实现此功能的任何提示。

非常感谢。

【问题讨论】:

    标签: python stream console subprocess


    【解决方案1】:

    在引用 selected answer 以从测试运行器流式输出时遇到一些问题。以下对我来说效果更好:

    import subprocess
    from time import sleep
    
    def stream_process(process):
        go = process.poll() is None
        for line in process.stdout:
            print(line)
        return go
    
    process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    while stream_process(process):
        sleep(0.1)
    

    【讨论】:

    • 只是说这非常适合我们的用例,感谢分享:)
    【解决方案2】:

    根据documentation

    Popen.poll()

    检查子进程是否已终止。设置并返回返回码属性。

    因此,基于此,您可以:

    process = subprocess.Popen('your_command_here',stdout=subprocess.PIPE)
    while True:
        output = process.stdout.readline()
        if process.poll() is not None and output == '':
            break
        if output:
            print (output.strip())
    retval = process.poll()
    

    这将循环,读取标准输出,并实时显示输出。


    这在当前版本的 python 中不起作用。 (至少)对于 Python 3.8.5 和更新版本,您应该将 output == '' 替换为 output == b''

    【讨论】:

    • 假设我不想简单地打印:我有一个单独的线程依赖于实时输出的数据。我将如何尽可能优雅地访问这些数据?除此之外,谢谢你的回答:-)
    • 使用上述过程从进程中提取的数据意味着在并行线程中运行的函数中进行处理。
    • 因此,不是打印output 变量,而是将其输入到您的函数中。我建议使用Queue - 它将包含strace 生成的output - 并让您的并行线程在可用时立即使用此队列中的数据。签出this
    • 还有一个问题:retval = process.poll() 是干什么用的?
    • 我猜 subprocess 已更改,因为您回答 b/c 我不得不将 ... and output == '' 更改为 ... and output == b'' 因为 process.stdout.readline() 正在返回字节字符串。否则循环永远不会终止。
    【解决方案3】:

    从 Python 3.2 开始(当上下文管理器支持添加到 Popen 时),我发现这是从子进程连续流式输出的最直接的方法:

    import subprocess
    
    
    def run(args):
      with subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) as process:
        for line in process.stdout:
          print(line.decode('utf8'))
    

    【讨论】:

    • 在 py3.8.5 下工作。比以前的解决方案优雅得多 - 我想知道这里是否有任何细微差别?相对于我之前使用的基于.poll() 的一个缺点是不能在所有情况下都超时(此方法必须 无限期地阻塞一行或EOF)......但仍然非常优雅
    猜你喜欢
    • 2021-05-26
    • 1970-01-01
    • 2015-06-08
    • 2016-12-01
    • 2014-04-20
    • 1970-01-01
    • 2021-08-30
    • 2021-01-18
    • 1970-01-01
    相关资源
    最近更新 更多