2012-09-04 22 views
3

所以我試圖捕獲HandBrakeCLI的輸出作爲Python子進程。這與stderr不存在問題,因爲每個更新都會在類文件管道中創建新行。但是,使用stdout,HandBrakeCLI會進行就地更新,並且我很難捕獲它們。我什至不知道就地更新被稱爲什麼,這使得找到相關的技巧有點棘手。難以捕獲進行就地狀態更新的子進程的輸出

我到目前爲止唯一的解決方案是將stdout寫入一個實際的文件並從中讀取,但我寧願這樣做(在內存中)。

COMMAND = ['HandBrakeCLI', '-v', '-i', 'in.m4v', '-o', 'out.m4v', '-Z', 'Normal'] 

outfile = open('output.txt', 'w') 

proc = subprocess.Popen(COMMAND, stdout=outfile, stderr=subprocess.PIPE) 

infile = open('output.txt', 'r') 

while proc.poll() is None: 
    print infile.read() 
    infile.seek(0) 

這是有效的,但必須有更好的方法。當試圖使用通信()或只是普通的proc.stdout.read()我什麼都沒有。

我在做什麼錯?謝謝!

更新

每@wim建議我檢查,看看有什麼原始輸出HandBrakeCLI提供,它看起來是這樣的:

\rEncoding: task 1 of 1, 0.15 % 

什麼是處理前綴爲一個標準輸出的最佳方式一個\ r?

+0

就地狀態更新如下所示:編碼:1的任務1,5.41%(134.10 fps,平均142.92 fps,ETA 00h25m39s) – kolanos

+1

我認爲您的問題可能是進度以'\ r'並從輸出讀取將基於行,即它將緩衝直到一個'\ n'。我曾經通過閱讀字節而不是線條來解決這個問題,並且自己去捕獲'\ r',但它非常難看。 – wim

+0

@wim:我相信你是對的。不幸的是,subprocess.stdout似乎沒有seek()方法。有哪些選項可用於搜索\ r的整個subprocess.stdout緩衝區?什麼是適當的bufsize呢?謝謝! – kolanos

回答

5

我認爲上面關於使用universal_newlines = True的評論會有效。

這裏有一個樣本就地作家,被稱爲「inplace_output.py」

import sys 
import time 


def main(): 
    for k in range(5): 
     print "{0:03d}\r".format(k), 
     sys.stdout.flush() 
     time.sleep(1) 

if __name__ == "__main__": 
    main() 

您可以運行,看它寫000,然後001,等等,每次覆蓋以前的輸出。

下面是運行上述作爲子進程的腳本,並通過行讀取輸出線:

import subprocess 


cmd = ['python', 'inplace_output.py'] 

proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, universal_newlines=True) 

while True: 
    out = proc.stdout.readline() 
    print repr(out) 
    if len(out) == 0: 
     break 

如果想在子計劃終止在一次收集所有的輸出,可以更換,而循環與,說,

out, err = proc.communicate() 
lines = out.splitlines() 

這些工作是否爲您?

+0

它們都顯得有效。謝謝! – kolanos