【问题标题】:python subprocess.readline() blocking when calling another python scriptpython subprocess.readline() 在调用另一个 python 脚本时阻塞
【发布时间】:2012-11-14 15:52:24
【问题描述】:

我一直在尝试使用 subprocess 模块将 python 脚本作为子进程运行,并且遇到了逐行读取输出的问题。

我阅读的文档表明您应该能够使用 subprocess 并在 stdout 上调用 readline(),如果我调用的脚本是 bash 脚本,这确实有效。但是,当我运行 python 脚本时,readline() 会阻塞,直到整个脚本完成。

我编写了几个重复问题的测试脚本。在测试脚本中,我尝试从 python 脚本 (tst.py) 中将 python 脚本 (tst1.py) 作为子进程运行,然后逐行读取 tst1.py 的输出。

tst.py 启动 tst1.py 并尝试逐行读取输出:

#!/usr/bin/env python
import sys, subprocess, multiprocessing, time
cmdStr = 'python ./tst1.py'
print(cmdStr)
cmdList = cmdStr.split()
subProc = subprocess.Popen(cmdList, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)

while(1):
    # this call blocks until tst1.py has completed, then reads all the output
    # it then reads empty lines (seemingly for ever)
    ln = subProc.stdout.readline()
    if ln:
        print(ln)

tst1.py 只是循环打印一条消息: #!/usr/bin/env python 进口时间

if __name__ == "__main__":
    x = 0
    while(x<20):
        print("%d: sleeping ..." % x)
        # flushing stdout here fixes the problem
        #sys.stdout.flush()
        time.sleep(1)
        x += 1

如果 tst1.py 写成 shell 脚本 tst1.sh:

#!/bin/bash
x=0

while [ $x -lt 20 ]
do
    echo $x: sleeping ...
    sleep 1
    let x++
done

readline() 按预期工作。

在玩了一些之后,我发现可以通过刷新 tst1.py 中的标准输出来解决这种情况,但我不明白为什么需要这样做。我想知道是否有人对此行为有解释?

我正在运行 redhat 4 linux: Linux lb-cbga-05 2.6.9-89.ELsmp #1 SMP Mon Apr 20 10:33:05 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux

【问题讨论】:

    标签: linux python-2.7


    【解决方案1】:

    因为如果输出被缓冲在某处,父进程将不会看到它,直到子进程在该点存在,输出被刷新并且所有 fd 都被关闭。至于为什么它在没有显式刷新输出的情况下与 bash 一起工作,因为当您在大多数 shell 中键入 echo 时,它实际上会派生一个执行 echo (打印一些东西)并存在的进程,所以输出也被刷新。

    【讨论】:

    • 感谢您的回答。我没有意识到 echo 分叉了一个单独的进程,因此我对 bash 脚本起作用感到困惑。大概这意味着标准输出默认由子进程缓冲。一个快速的谷歌告诉我,你可以使用 expect unbuffer 来解决这个问题,虽然我还没有尝试过。
    • ...抱歉不小心按了返回。
    • @user1802664 不客气,如果这回答了您的问题,请接受,谢谢。
    猜你喜欢
    • 2013-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多