python subprocess.readline()在调用另一个python脚本时阻塞

时间:2012-11-14 15:52:24

标签: linux python-2.7

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

我读过的文档表明你应该能够在stdout上使用subprocess并调用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中刷新stdout来解决这个问题,但是我不明白为什么这是必需的。我想知道是否有人对此行为有解释?

我正在运行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

1 个答案:

答案 0 :(得分:0)

因为如果输出缓存在某个地方,父进程将不会看到它,直到该进程存在子进程,刷新输出并关闭所有fd。至于为什么它在没有显式刷新输出的情况下使用bash,因为当你在大多数shell中键入echo时,它实际上会执行一个执行echo的进程(打印一些东西)并存在,因此输出也被刷新。