簡體   English   中英

Python:在不打印文件的情況下讀取子流程的標准輸出

[英]Python: Reading a subprocess' stdout without printing to a file

我有一個名為BOB.exe的可執行函數,該函數只需短暫停頓即可將大量文本輸出到stdout。 BOB也有凍結的習慣,因此我編寫了一個python監視函數,該函數使用子進程模塊調用BOB可執行文件,將其定向到臨時文件,並觀察臨時文件的大小以查看其是否崩潰。 這是我目前的解決方案:

#!/usr/bin/python
from subprocess import Popen
import tempfile, time
def runBOB(argsList):

    # Create a temporary file where BOB stdout will be piped
    BOBout = tempfile.NamedTemporaryFile()
    BOBoutSize = 0

    # Start the subprocess of BOB
    BOBsp = Popen(argsList, stdout=BOBout)

    while True:
        # See if subprocess has finished
        if BOBsp.poll() is not None:
            BOBout.close() # Destroy the temp file
            return 0

        # if the size of the stdout file has increased, BOB.exe is still running
        BOBoutSizeNew = os.path.getsize(BOBout.name)
        if BOBoutSizeNew > BOBoutSize:
            BOBoutSize = BOBoutSizeNew
        else: # if not, kill it
            BOBsp.kill()
            BOBout.close() # Destroy the temp file
            return 1

        # Check every 10 seconds
        time.sleep(10)

但是,這太慢了,我認為是寫文件的原因。 有沒有更有效的方法來做到這一點,例如觀看stdout流,然后立即將其發送到Null? 減少任何已完成的打印工作的事情都可能會有所幫助。 還有另一種查看exe是否崩潰的方法嗎? 我可能應該注意,我不在乎標准輸出,無論如何都將被忽略。

謝謝您的幫助!

您可以使用stdout=subprocess.PIPE告訴subprocess讓您能夠讀取子流程的輸出而不將其存儲到文件中。 棘手的部分是異步執行此操作,以免BOB.exe凍結時死鎖。 一種簡單的方法是使用幫助線程。 盡管Python在線程方面的聲譽很差,但是對於GIL不會妨礙線程的線程來說,這實際上是一個很好的用例。

只需創建一個幫助線程,該線程除了從文件句柄讀取與Bob的輸出相對應的輸出外,什么也不做。 幫助線程立即丟棄輸出,並增加一個字節計數器。 主線程實現與以前完全相同的邏輯,但是使用內存中計數器,而不是重新檢查文件大小。 當Bob完成或被主線程殺死時,輔助線程將收到EOF並退出。

這是上述的未經測試的實現:

#!/usr/bin/python
import subprocess
import threading
import time
import os

bytes_read = 0

def readBOB(pipe):
    global bytes_read
    bytes_read = 0
    while True:
        # Wait for some data to arrive. This must use os.read rather
        # than pipe.read(1024) because file.read would block us if less
        # than 1024 bytes of data arrives. (Reading one byte at a time
        # with pipe.read(1) would work, but would be too slow at
        # consuming large amounts of data.)
        s = os.read(pipe.fileno(), 1024)
        if not s:
            return  # EOF
        # we are the only writer, so GIL serves as the lock
        bytes_read += len(s)

def runBOB(argsList):
    # Start the subprocess of BOB
    BOBsp = subprocess.Popen(argsList, stdout=subprocess.PIPE)

    thr = threading.Thread(target=readBOB, args=(BOBsp.stdout,))
    thr.start()
    old_bytes_read = -1

    while True:
        # See if subprocess has finished
        if BOBsp.poll() is not None:
            return 0

        # if the size of the stdout has increased, BOB.exe is still running
        new_bytes_read = bytes_read

        if new_bytes_read > old_bytes_read:
            old_bytes_read = new_bytes_read
        else: # if not, kill it (readBOB will exit automatically)
            BOBsp.kill()
            return 1

        # Check every 10 seconds
        time.sleep(10)

暫無
暫無

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

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