2013-05-15 94 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中的線程非常簡單,我可以提供一個例子,如果你需要的話。