python脚本之间的管道

时间:2015-11-09 11:42:00

标签: python bash pipe

我有一个简单的脚本,它从设备读取值并通过print输出它们,另一个脚本监听stdin并解释每个数字。设备每秒输出一个数字。令人惊讶的是,在我的ubuntu盒子上管道脚本不起作用。但是,如果第一个脚本不是从设备读取而是尽可能快地生成随机数,则第二个脚本会成功接收数据。

以下是我的情况的简化示例。

print.py:

#!/usr/bin/env python2
import time
import sys

while True:
    time.sleep(1)  # without this everything works
    print "42"
    sys.stdout.flush()

read.py:

#!/usr/bin/env python2
import sys

while True:
    for str in sys.stdin:
        print str

命令行调用:

vorac@laptop:~/test$ ./print.py | ./read.py

这是最终结果。第一个脚本从设备读取,第二个脚本在两个不同的时间帧中绘制数据(显示的是随机数)。

enter image description here

2 个答案:

答案 0 :(得分:3)

啊,现在这是一个棘手的问题。之所以会发生这种情况,是因为sys.stdinxreadlines())的迭代器方法是缓冲的。换句话说,当你的循环隐式调用next(sys.stdin)来获取下一行输入时,Python tries to read来自真正的底层标准输入流,直到它的内部缓冲区已满,并且只有一次缓冲区它是否已经通过循环体进行。 buffer size is 8 kilobytes,所以这需要一段时间。

您可以通过减少sleep()调用0.001或某些此类值的时间延迟来查看此信息,具体取决于系统的功能。如果你恰到好处的时间,你几秒钟内什么也看不见,然后整整一块42一下子全部出来。

要解决此问题,请使用未缓冲的sys.stdin.readline()

while True:
    line = sys.stdin.readline()
    print line

您可能还希望在打印前删除尾随换行符,否则您将获得双重换行符。使用line.rstrip('\n')print line,来抑制要打印的额外换行符。

答案 1 :(得分:2)

我更改了你的read.py,它对我有用:),你忘了.readline()来自stdin

import sys
while True:
    line = sys.stdin.readline()
    if line:
        print line.strip()
    else:
        continue

输出是:

$ python write.py | python read.py 
42
42
42
42
42
42
42