Python- 从subprocess.communicate()读取流输入

发布于 2021-02-02 23:23:55

我正在使用Python subprocess.communicate()从运行约一分钟的进程中读取stdout。

我该如何stdout以流方式打印出该流程的每一行,以便可以看到生成的输出,但仍然阻止该流程终止,然后再继续?

subprocess.communicate() 似乎一次给出所有输出。

关注者
0
被浏览
215
1 个回答
  • 面试哥
    面试哥 2021-02-02
    为面试而生,有面试问题,就找面试哥。

    这是一个简单的示例(不检查错误):

    import subprocess
    proc = subprocess.Popen('ls',
                           shell=True,
                           stdout=subprocess.PIPE,
                           )
    while proc.poll() is None:
        output = proc.stdout.readline()
        print output,
    

    如果ls结束太快,则while循环可能会在你读取所有数据之前结束。

    你可以通过以下方式在stdout中捕获其余部分:

    output = proc.communicate()[0]
    print output,
    


  • 面试哥
    面试哥 2021-02-02
    为面试而生,有面试问题,就找面试哥。

    要在子进程刷新其stdout缓冲区后逐行获取子进程的输出:

    #!/usr/bin/env python2
    from subprocess import Popen, PIPE
    
    p = Popen(["cmd", "arg1"], stdout=PIPE, bufsize=1)
    with p.stdout:
        for line in iter(p.stdout.readline, b''):
            print line,
    p.wait() # wait for the subprocess to exit
    

    iter()用于在编写行后立即读取行,以解决Python 2中的预读错误。

    如果子进程的stdout在非交互模式下使用块缓冲而不是行缓冲(这会导致输出延迟,直到子缓冲区已满或被子进程显式刷新),然后你可以尝试使用以下方式强制使用无缓冲输出 pexpect,pty模块或unbuffer,stdbuf,script公用事业,见问:为什么不直接使用管道(popen方法())?

    这是Python 3代码:

    #!/usr/bin/env python3
    from subprocess import Popen, PIPE
    
    with Popen(["cmd", "arg1"], stdout=PIPE, bufsize=1,
               universal_newlines=True) as p:
        for line in p.stdout:
            print(line, end='')
    

    注意:与Python 2不同,Python 2照原样输出子进程的字节串。Python 3使用文本模式(使用locale.getpreferredencoding(False)编码对cmd的输出进行解码)。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看