python - 当子进程在 Python 中运行时,如何从子进程 PIPE 获取数据?

标签 python multithreading pyqt subprocess qthread

我在 Windows 上有一个程序调用一堆子进程,并在 GUI 中显示结果。我使用 PyQt 作为 GUI,使用 subprocess 模块来运行程序。

我有以下 WorkerThread,它为每个 shell 命令生成一个子线程,专门用于读取进程 stdout 并打印结果(稍后我将连接它直到 GUI)。

这一切都有效。 Except proc.stdout.read(1) never 在子进程完成之前返回。这是个大问题,因为其中一些子流程可能需要 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 不接收任何数据,直到底层进程返回。然后我一下子得到所有东西。

最佳答案

如果您知道命令输出行的长度,您可以在进程的标准输出 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)

也许这不是您要找的东西,但我认为它可以让您很好地了解如何解决您的问题。

编辑:我想我刚刚找到了您需要的东西Streaming stdout from a Python subprocess in Python .

关于python - 当子进程在 Python 中运行时,如何从子进程 PIPE 获取数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20685249/

相关文章:

pthreads 和 curl 之间的 PHP 测试

c++ - 为什么 INSERT 和 DELETE 会搞砸 QTableView(Qt、C++、sqlite)?

qt - python qt : automatically resizing main window to fit content

python - 在 PyQt 中使用计时器更新标签

python - 使用 paramiko 和 sshtunnel 与 docker alpine 的 libssl 问题

python - 为多个分类编辑 tensorflow inceptionV3 retraining-example.py

java - 如何分析java线程转储?

python - 为什么要使用udacity gui和scipy从wav文件中提取样本,并给出不同的值?

python - 在没有 with-as 子句的情况下向图表添加操作

维护进程池的 Java 库