【问题标题】:subprocess: can't get live output if time between outputs is too big子流程:如果输出之间的时间过长,则无法获得实时输出
【发布时间】:2018-08-03 10:15:46
【问题描述】:

我想在另一个 Python 脚本 (run_python_script.py) 中启动一个 Python 脚本(我将其称为 test.py)。为此,我使用如下所示的子进程命令:https://stackoverflow.com/a/18422264

那就是 run_python_script.py

import subprocess
import sys
import io
import time


def runPython(filename, filename_log="log.txt"):

    with io.open(filename_log, 'wb') as writer, io.open(filename_log, 'rb', 1) as reader:
        process = subprocess.Popen("python {}".format(filename), stdout=writer)
        while process.poll() is None:
            sys.stdout.write(reader.read().decode("utf-8"))
            time.sleep(0.5)
        # Read the remaining
        sys.stdout.write(reader.read().decode("utf-8"))


runPython("test.py")

这是 test.py

import time

sleep_time = 0.0001
start_time = time.time()

for i in range(10000):
    print(i)
    time.sleep(sleep_time)
print(time.time() - start_time)

在此设置中,实时输出有效,但如果 sleep_time(在 test.py 中)过大,例如 sleep_time = 1run_python_script.py 仅在 test.py 完成后输出。
我将 time.sleep(sleep_time) 替换为其他函数,每个需要很长时间的函数都会破坏实时输出。

当然 test.py 只是一个例子。我想用其他方法,结果是一样的。

【问题讨论】:

    标签: python python-3.x subprocess


    【解决方案1】:

    要从子进程获取实时输出,您需要进行一些缓冲区刷新。我假设您使用的是 Python 3,它支持 flush arg 到 print 函数。

    我还假设您想将文本数据从子级传递给父级,但传递二进制数据也很容易:去掉 universal_newlines=True 并将 bufsize 更改为零(或一些适合的缓冲区大小您的数据)。

    yannick_test.py

    from time import sleep, perf_counter
    
    sleep_time = 0.5
    start_time = perf_counter()
    
    for i in range(10):
        print(i, flush=True)
        sleep(sleep_time)
    
    print(perf_counter() - start_time)
    

    run_python_script.py

    from subprocess import Popen, PIPE
    
    def run_python(filename):
        process = Popen(["python3", filename],
            universal_newlines=True, bufsize=1, stdout=PIPE)
        for data in process.stdout:
            print(data, end='', flush=True)
    
    run_python("yannick_test.py")
    

    典型输出

    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
    5.0068185229974915
    

    虽然这可行,但构建子脚本会更有效,这样您就可以直接导入它们并调用它们的函数,如果需要同时运行,也可以使用线程或多处理。

    【讨论】:

    • 太棒了,谢谢!我知道这不是最有效的方法,但我认为在我的情况下还可以。
    猜你喜欢
    • 2020-11-27
    • 1970-01-01
    • 2020-07-22
    • 2014-05-14
    • 1970-01-01
    • 2021-11-30
    • 1970-01-01
    • 1970-01-01
    • 2018-05-20
    相关资源
    最近更新 更多