簡體   English   中英

檢查python中正在運行的子進程的stdout

[英]Check on the stdout of a running subprocess in python

如果需要定期檢查正在運行的進程的stdout 例如,進程是tail -f /tmp/file ,它是在python腳本中生成的。 然后每隔x秒,該子進程的stdout被寫入字符串並進一步處理。 腳本最終會停止子進程。

要解析子check_output的stdout,如果直到現在使用check_output ,這似乎不起作用,因為進程仍在運行並且不會產生確定的輸出。

>>> from subprocess import check_output
>>> out = check_output(["tail", "-f", "/tmp/file"])
 #(waiting for tail to finish)

應該可以為子進程使用線程,以便可以處理多個子進程的輸出(例如tail -f / tmp / file1,tail -f / tmp / file2)。

如何啟動子進程,定期檢查和處理其標准輸出並最終以多線程友好的方式停止子進程? python腳本在Linux系統上運行。

目標不是連續讀取文件,tail命令是一個示例,因為它的行為與使用的實際命令完全相同。

編輯:我沒想到這個,文件不存在。 check_output現在只是等待進程完成。

edit2:另一種方法,使用PopenPIPE似乎會導致同樣的問題。 它等待tail完成。

>>> from subprocess import Popen, PIPE, STDOUT
>>> cmd = 'tail -f /tmp/file'
>>> p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
>>> output = p.stdout.read()
 #(waiting for tail to finish)

你的第二次嘗試是正確的90%。 唯一的問題是你試圖在它完成后同時閱讀所有 tail的標准輸出。 但是, tail應該在后台運行(無限期?),所以你真的想逐行讀取stdout:

from subprocess import Popen, PIPE, STDOUT
p = Popen(["tail", "-f", "/tmp/file"], stdin=PIPE, stdout=PIPE, stderr=STDOUT)
for line in p.stdout:
    print(line)

我刪除了shell=Trueclose_fds=True參數。 第一個是不必要的,有潛在危險,而第二個是默認值。

請記住,文件對象可以在Python中通過它們的行進行迭代。 for循環將一直運行,直到tail死亡,但它將處理每條線,而不是read ,這將阻塞直到tail死亡。

如果我在/tmp/file創建一個空文件,啟動該程序並開始使用另一個shell將行回顯到文件中,程序將回顯這些行。 您可能應該用更有用的東西替換print

以下是我在啟動上述代碼后輸入的命令示例:

命令行

$ echo a > /tmp/file
$ echo b > /tmp/file
$ echo c >> /tmp/file

程序輸出(來自不同shell中的Python)

b'a\n'
b'tail: /tmp/file: file truncated\n'
b'b\n'
b'c\n'

如果您希望主程序在響應tail的輸出時響應,請在單獨的線程中啟動循環。 您應該將此線程設置為守護程序,以便即使tail未完成也不會阻止程序退出。 您可以讓線程打開子流程,也可以將標准輸出傳遞給它。 我更喜歡后一種方法,因為它可以讓你在主線程中有更多的控制權:

def deal_with_stdout():
    for line in p.stdout:
        print(line)

from subprocess import Popen, PIPE, STDOUT
from threading import Thread
p = Popen(["tail", "-f", "/tmp/file"], stdin=PIPE, stdout=PIPE, stderr=STDOUT)
t = Thread(target=deal_with_stdout, daemon=True)
t.start()
t.join()

這里的代碼幾乎相同,添加了一個新線程。 我在最后添加了一個join() ,所以程序作為一個例子表現得很好( join在返回之前等待線程死掉)。 您可能希望用通常運行的任何處理代碼替換它。

如果您的線程足夠復雜,您可能還希望從Thread繼承並覆蓋run方法而不是傳入一個簡單的target

暫無
暫無

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

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