我在Windows上有一个调用大量子进程的程序,并在GUI中显示结果。我正在使用PyQt作为GUI,使用subprocess
模块来运行程序。
我有以下WorkerThread
,它为每个shell命令生成一个子线程,专门用于读取进程 stdout 并打印结果(稍后我会将其连接到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
不接收任何数据。然后我立刻得到了所有的东西。
答案 0 :(得分:1)
如果您知道命令输出行的长度,您可以在进程的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。