簡體   English   中英

Python - 捕獲Popen stdout並在控制台上顯示?

[英]Python - capture Popen stdout AND display on console?

我想從通過subprocess.Popen(...)啟動的長時間運行進程捕獲stdout所以我使用stdout=PIPE作為arg。

但是,因為它是一個長時間運行的進程,我還想將輸出發送到控制台(好像我沒有管道它)給腳本用戶一個它仍在工作的想法。

這是可能嗎?

干杯。

緩存你的長時間運行的子進程可能會使你的控制台輸出生澀和非常糟糕的用戶體驗。 我建議你考慮使用pexpect (或者,在Windows上, wexpect )來打敗這樣的緩沖並從子進程獲得平滑,規則的輸出。 例如(在任何unix-y系統上,安裝pexpect之后):

>>> import pexpect
>>> child = pexpect.spawn('/bin/bash -c "echo ba; sleep 1; echo bu"', logfile=sys.stdout); x=child.expect(pexpect.EOF); child.close()
ba
bu
>>> child.before
'ba\r\nbu\r\n'

ba和bu將具有適當的時間(它們之間大約一秒)。 請注意,輸出不受正常的終端處理,因此回車留在那里 - 你需要自己后處理字符串(只是一個簡單的.replace ! - ),如果你需要\\n作為結束-line標記(缺少處理非常重要,以防子進程將二進制數據寫入其stdout - 這可確保所有數據保持完整! - )。

S. Lott的評論指出使用子 進程 獲取實時輸出在Python中實時攔截來自另一個進程的stdout

我很好奇亞歷克斯的答案與他的答案1085071不同。我在其他兩個引用問題中的答案的簡單小實驗已經給出了很好的結果......

我按照亞歷克斯的回答看了看wexpect,但我不得不說讀代碼中的注釋我對使用它沒有很好的感覺。

我想這里的元問題是什么時候pexpect / wexpect會成為包含的電池之一?

您可以在從管道中讀取時將其print出來嗎?

或者,您可以將流程導入tee並僅捕獲其中一個流。 sh -c 'process interesting stuff' | tee /dev/stderr某些東西sh -c 'process interesting stuff' | tee /dev/stderr sh -c 'process interesting stuff' | tee /dev/stderr

當然,這只適用於類Unix系統。

靈感來自上面某處的pty.openpty()建議,在python2.6,linux上測試過。 發布以來需要一段時間才能使其正常工作,無需緩沖......

def call_and_peek_output(cmd, shell=False):
    import pty, subprocess
    master, slave = pty.openpty()
    p = subprocess.Popen(cmd, shell=shell, stdin=None, stdout=slave, close_fds=True)
    os.close(slave)
    line = ""
    while True:
        try:
            ch = os.read(master, 1)
        except OSError:
            # We get this exception when the spawn process closes all references to the
            # pty descriptor which we passed him to use for stdout
            # (typically when it and its childs exit)
            break
        line += ch
        sys.stdout.write(ch)
        if ch == '\n':
            yield line
            line = ""
    if line:
        yield line

    ret = p.wait()
    if ret:
        raise subprocess.CalledProcessError(ret, cmd)

for l in call_and_peek_output("ls /", shell=True):
    pass

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM