繁体   English   中英

Python - 捕获Popen stdout并在控制台上显示?

[英]Python - capture Popen stdout AND display on console?

我想从通过subprocess.Popen(...)启动的长时间运行进程捕获stdout所以我使用stdout=PIPE作为arg。

但是,因为它是一个长时间运行的进程,我还想将输出发送到控制台(好像我没有管道它)给脚本用户一个它仍在工作的想法。

这是可能吗?

干杯。

缓存你的长时间运行的子进程可能会使你的控制台输出生涩和非常糟糕的用户体验。 我建议你考虑使用pexpect (或者,在Windows上, wexpect )来打败这样的缓冲并从子进程获得平滑,规则的输出。 例如(在任何unix-y系统上,安装pexpect之后):

>>> import pexpect
>>> child = pexpect.spawn('/bin/bash -c "echo ba; sleep 1; echo bu"', logfile=sys.stdout); x=child.expect(pexpect.EOF); child.close()
ba
bu
>>> child.before
'ba\r\nbu\r\n'

ba和bu将具有适当的时间(它们之间大约一秒)。 请注意,输出不受正常的终端处理,因此回车留在那里 - 你需要自己后处理字符串(只是一个简单的.replace ! - ),如果你需要\\n作为结束-line标记(缺少处理非常重要,以防子进程将二进制数据写入其stdout - 这可确保所有数据保持完整! - )。

S. Lott的评论指出使用子 进程 获取实时输出在Python中实时拦截来自另一个进程的stdout

我很好奇亚历克斯的答案与他的答案1085071不同。我在其他两个引用问题中的答案的简单小实验已经给出了很好的结果......

我按照亚历克斯的回答看了看wexpect,但我不得不说读代码中的注释我对使用它没有很好的感觉。

我想这里的元问题是什么时候pexpect / wexpect会成为包含的电池之一?

您可以在从管道中读取时将其print出来吗?

或者,您可以将流程导入tee并仅捕获其中一个流。 sh -c 'process interesting stuff' | tee /dev/stderr某些东西sh -c 'process interesting stuff' | tee /dev/stderr sh -c 'process interesting stuff' | tee /dev/stderr

当然,这只适用于类Unix系统。

灵感来自上面某处的pty.openpty()建议,在python2.6,linux上测试过。 发布以来需要一段时间才能使其正常工作,无需缓冲......

def call_and_peek_output(cmd, shell=False):
    import pty, subprocess
    master, slave = pty.openpty()
    p = subprocess.Popen(cmd, shell=shell, stdin=None, stdout=slave, close_fds=True)
    os.close(slave)
    line = ""
    while True:
        try:
            ch = os.read(master, 1)
        except OSError:
            # We get this exception when the spawn process closes all references to the
            # pty descriptor which we passed him to use for stdout
            # (typically when it and its childs exit)
            break
        line += ch
        sys.stdout.write(ch)
        if ch == '\n':
            yield line
            line = ""
    if line:
        yield line

    ret = p.wait()
    if ret:
        raise subprocess.CalledProcessError(ret, cmd)

for l in call_and_peek_output("ls /", shell=True):
    pass

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM