Python subprocess.poll() 个问题

Python subprocess.poll() questions

我正在使用 Python 的子进程模块,在轮询 运行ning 进程时遇到问题。

我的最终目标是从 stdout 中获取每一行,评估它打印出主进程 stdout 的相关新行,因为它 运行s。问题是,当我轮询一个测试程序时,它似乎在等待子进程完成,然后再向 stdout 输出任何内容。当我向父程序引入一个time.sleep(1)方法时它就是这样做的。

家长计划

import subprocess
import time
def runProcess():
    process = subprocess.Popen([
        'py.exe',
        'subpy.py'],
        stdin=subprocess.PIPE,
        stderr=subprocess.PIPE,
        stdout=subprocess.PIPE)
    while process.poll() == None:
        print('.', end ="")
        time.sleep(1)

runProcess()
input("press enter to exit.")

子程序

import random, time

for x in range(1,5):
    time.sleep(1)
    value = random.randint(1,3)
    if value == 1: 
        print("hello")
    if value == 2:
        print('goodbye')
    if value == 3:
        print('im not sure')
exit()

如有任何帮助,我们将不胜感激!

PS:

我的 parent 过程的最终目标看起来像这样,尽管我不确定这是否会 运行 在输出完全完成之前进入轮询问题。

import subprocess
import time
def runProcess():
    process = subprocess.Popen([
        'py.exe',
        'subpy.py'],
        stdin=subprocess.PIPE,
        stderr=subprocess.PIPE,
        stdout=subprocess.PIPE)
    while process.poll() == None:
        stdout, stderr = subprocess.communicate()
        if stdout == '':
            print('.', end ="")
            time.sleep(1)
        if stdout == "goodbye" or stdout == 'hello'
            print(">>> %s" % stdout)
        else:
            print(stdout)

runProcess()
input("press enter to exit.")

创建进程后,可以读取其stdout直到关闭,说明进程已经关闭。但是有几个问题。

首先是进程可能会填满 stderr 并阻止尝试写入更多内容。这可以通过为您读取 stderr 的后台线程来解决。在这个例子中,我只是将它复制到一个 in-memory 缓冲区中,以便在进程退出后读取。还有其他选项,具体取决于您要对数据流执行的操作。

然后是 stdout 管道多久冲洗一次的问题。由于它是一个管道,写入是块缓冲的。如果没有来自子进程的刷新,您将无法实时获得输出。在 unix-like 系统中,您可以用 pseudo-tty 替换管道(参见 pty 模块)。但这是 Windows,因此在调用过程中您无能为力。最终发生的事情是,你根据子库刷新的时间(或者你在代码中放置了很多刷新)来分组获取传入行。

import subprocess
import sys
import io
import time
import shutil
import threading

def runProcess():
    process = subprocess.Popen([
        sys.executable,
        'subpy.py'],
        stdin=subprocess.PIPE,
        stderr=subprocess.PIPE,
        stdout=subprocess.PIPE)
    process.stdin.close()
    err_buf = io.BytesIO()
    err_thread = threading.Thread(target=shutil.copyfileobj,
            args=(process.stderr, err_buf))
    err_thread.start()
    for line in process.stdout:
        line = line.decode() # defaulting to system encoding
        print(line,end='',flush=True)
    process.wait()
    err_thread.join()
    err_buf.seek(0)
    print("Errors:", err_buf.read().decode())

runProcess()
input("press enter to exit.")