2013-05-15 93 views
0

我以为每个进程管道连接的工作是异步的,但事实并非如此。Shell管道异步工作

a.py

#!/usr/bin/env python 
import sys 
import time 
for line in sys.stdin: 
    time.sleep(2) 
    sys.stdout.write(line.upper()) 
    sys.stdout.flush() 

和b.py

#!/usr/bin/env python 
import sys 
for line in sys.stdin: 
    sys.stdout.write(line.capitalize()) 
    sys.stdout.flush() 

和test.txt的

hello 
world 
python 

以下代码显示每行一个一个由2秒。

$ ./a.py < test.txt 
HELLO 
WORLD 
PYTHON 

但下面的代码完全显示了一次。

$ ./a.py < test.txt | ./b.py 
Hello 
World 
Python 

看起来管壳是同步工作的。我怎样才能异步?

回答

0

与代码的问题是,虽然表情...

for line in sys.stdin: 
    # ... 

被处理sys.stdin作为一个迭代器,它似乎...不产生任何值,直到sys.stdin命中EOF,多像sys.stdin.readlines()的行为一样。

对于第一种情况,它几乎立即碰到EOF,但在第二种情况下,它必须等待a.py终止,这需要6秒。

你必须重写代码为b.py这样的...

#!/usr/bin/env python 
import sys 
while 1: 
    line = sys.stdin.readline() 
    if not line: 
     break 
    sys.stdout.write(line.capitalize()) 
    sys.stdout.flush() 

...使用readline()得到调用,因为它有一整行尽快返回,而不是等待EOF。

如果您想要输入来自除文本文件之外的输入,您应该也可以对a.py进行类似更改。

+0

感谢您的回答。我在http://stackoverflow.com/a/7608205/395425中找到了类似的线程。在python2.7中,“for”语句正在等待EOF,但python3.3不会等待。 –

+1

我后来发现,python 2.x“for sys.stdin中的行”不会等到EOF。它似乎在缓冲。 –

0

你可以使用线程,但我不知道这是否适合你的喜好。 ;)

ps:python中的线程非常简单,我可以提供一个例子,如果你需要的话。