2013-01-22 16 views
7

好吧,所以我見過這麼多的線程,但沒有一個給出了完整的答案,我試過的所有東西迄今爲止都不適用於我。使用subprocess.Popen調用python腳本並刷新數據

1)的腳本不斷輸出一些數據和flusheshs它:

import time 
import sys 

if __name__ == '__main__': 
    for i in range(5): 
     print i, 
     sys.stdout.flush() 
     time.sleep(1) 

2)腳本調用第一個腳本與POPEN,應由之一,但由於某些原因沒有被印刷的數字之一,並將它們打印產品總數一次:

import sys 
import subprocess 

if __name__ == '__main__': 
    process = subprocess.Popen(['python', 'flush.py'], stdout = subprocess.PIPE) 
    for line in iter(process.stdout.readline, ''): 
     print line, 
     sys.stdout.flush() 

第一件事,我很困惑一點點在第一腳本是,如果你刪除刷新它返回輸出在一行一起O_O ...我非常確定這是因爲time.sleep,但仍然有點期望它返回像一個標準輸出不斷返回值0,1,2 ,3,4但不是全部一起着,當然沖洗解決它,只是奇怪,至少對我來說...

的主要問題: 那是第二個腳本沒有一個返回一個數字,但回報所有在一個輸出一次.....我需要的是看到數字一個接一個彈出...

我讀了一個地方,它不返回EOF,Popen等待關閉管道,這就是爲什麼它運行喜歡結束.....

那麼我該怎麼做或接下來嘗試? 在此先感謝。

+1

很可能是因爲您的子流程在每個數字後都沒有打印換行符。 'readline'讀取直到換行符(或文件結尾)。看看我的答案在這裏是否有所幫助:http://stackoverflow.com/questions/12255802/having-difficulty-capturing-output-of-a-subprocess-that-does-in-place-status-upd/12256356#12256356 –

+1

那麼,基本上我找到了解決我的問題。雖然我沒有真正理解它背後的理論,但代碼是有效的[link](http://chase-seibert.github.com/blog/2012/11/16/python-subprocess-asynchronous-read-stdout的.html)。爲什麼你在線程中執行它,在某處我讀取不阻止主線程,但接下來又是如何提供幫助,如果仍然只是在線程中將整個文本集中在一起,那對我來說沒有意義,因爲我不明白它是如何實現的我猜的作品。那麼關於將文件描述符設置爲非阻塞的問題也會讓我感到困惑。 – Viktor

+0

@Viktor:[您提供的鏈接](http://chase-seibert.github.com/blog/2012/11/16/python-subprocess-asynchronous-read-stdout.html)是不必要的複雜。它的工作原理是因爲它不使用'readline()'(對於非阻塞管道來說不起作用),因此它不會等待子腳本永遠不會生成的換行符。這裏有一個[更簡單的解決方案,在很多情況下應該足夠用於面向行的輸出](http://stackoverflow.com/a/17698359/4279) – jfs

回答

4

由於@Warren Weckesser's comment表示,您的問題與buffering issues無關。

.readline()在父進程中將不會返回,直到它讀取一個換行符或達到EOF。您的子進程不打印任何換行符,因此您的父進程不會打印任何東西,直到子進程結束。

最小修復只是在子腳本中刪除print i,末尾的逗號。

這也適用:

#!/usr/bin/env python 
import sys 
from subprocess import Popen, PIPE 

p = Popen([sys.executable or 'python', 
      '-u', # unbuffer stdout (or make it line-buffered on Python 3) 
      '-c', 
      """ 
import time 

for i in range(5): 
    print(i) # <-- no comma i.e., each number is on its own line 
    time.sleep(1) 
"""], stdout=PIPE, bufsize=1) 
for line in iter(p.stdout.readline, b''): 
    print(int(line)**2) 

實施例:

$ python parent.py 
0 
1 
4 
9 
16 

的號碼被每秒印刷,而無需等待子進程結束。

如果你不想改變孩子的腳本,那麼你應該使用readline()停在空白的,而不是一個換行符例如:

#!/usr/bin/env python 
import sys 
from subprocess import Popen, PIPE 

p = Popen(['python2', 'child.py'], stdout=PIPE, bufsize=0) 
for token in generate_tokens(p.stdout): 
    print(int(token)) 

其中generate_tokens()產生空格分隔的標記:

def generate_tokens(pipe): 
    buf = [] 
    while True: 
     b = pipe.read(1) # read one byte 
     if not b: # EOF 
      pipe.close() 
      if buf: 
       yield b''.join(buf) 
      return 
     elif not b.isspace(): # grow token 
      buf.append(b) 
     elif buf: # full token read 
      yield b''.join(buf) 
      buf = [] 

它也打印整數,只要他們打印的孩子。