簡體   English   中英

當子進程在Python中運行時,如何從子進程PIPE獲取數據?

[英]How do I get data from a subprocess PIPE while the subprocess is running in Python?

我在Windows上有一個調用大量子進程的程序,並在GUI中顯示結果。 我正在使用PyQt作為GUI,並使用subprocess模塊來運行程序。

我有以下WorkerThread ,它為每個shell命令生成一個子線程,專門用於讀取進程標准輸出並打印結果(稍后我將它連接到GUI)。

這一切都有效。 proc.stdout.read(1) 永遠不會返回,直到子進程完成之后。 這是一個很大的問題,因為其中一些子進程可能需要15-20分鍾才能運行,我需要在運行時顯示結果。

在子進程運行時,我需要做什么才能使管道正常工作?

class WorkerThread(QtCore.QThread):
    def run(self):
        def sh(cmd, cwd = None):
            proc = subprocess.Popen(cmd,
                                    shell = True,
                                    stdout = subprocess.PIPE,
                                    stderr = subprocess.STDOUT,
                                    stdin = subprocess.PIPE,
                                    cwd = cwd,
                                    env = os.environ)

            proc.stdin.close()

            class ReadStdOutThread(QtCore.QThread):
                def run(_self):
                    s = ''
                    while True:
                        if self.request_exit: return

                        b = proc.stdout.read(1)
                        if b == '\n':
                            print s
                            s = ''
                            continue

                        if b:
                            s += b
                            continue

                        if s: print s
                        return

            thread = ReadStdOutThread()
            thread.start()

            retcode = proc.wait()
            if retcode:
                raise subprocess.CalledProcessError(retcode, cmd)

            return 0

FWIW:我用QProcess重寫了整個事情,我看到了完全相同的問題。 在基礎進程返回之前, stdout接收任何數據。 然后我立刻得到了所有的東西。

如果您知道命令輸出行的長度,您可以在進程的stdout PIPE上進行輪詢。

我的意思的一個例子:

import select
import subprocess
import threading
import os

# Some time consuming command.
command = 'while [ 1 ]; do sleep 1; echo "Testing"; done'

# A worker thread, not as complex as yours, just to show my point.
class Worker(threading.Thread):

    def __init__(self):
        super(Worker, self).__init__()
        self.proc = subprocess.Popen(
            command, shell=True, 
            stdout=subprocess.PIPE, 
            stdin=subprocess.PIPE, stderr=subprocess.STDOUT
        )

    def run(self):
        self.proc.communicate()


    def get_proc(self):
        # The proc is needed for ask him for his
        # output file descriptor later.
        return self.proc


if __name__ == '__main__':
    w = Worker()
    w.start()

    proc = w.get_proc()

    pollin = select.poll()

    pollin.register(proc.stdout, select.POLLIN)


    while ( 1 ):
        events = pollin.poll()
        for fd, event in events:
             if event == select.POLLIN:
                 # This is the main issue of my idea,
                 # if you don't know the length of lines
                 # that process ouput, this is a problem.
                 # I put 7 since I know the word "Testing" have
                 # 7 characters.
                 print os.read(fd, 7)

也許這不是您正在尋找的,但我認為它可以讓您很好地了解如何解決您的問題。

編輯 :我想我剛從Python中的Python子進程中找到了你需要的Streaming stdout

暫無
暫無

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

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