Python 如何运行子进程、在GUI中显示其输出并允许终止它?
我一直在尝试编写一个应用程序来运行子流程,并(除其他外)在GUI中显示它们的输出,并允许用户单击按钮取消它们。我开始这样的过程:Python 如何运行子进程、在GUI中显示其输出并允许终止它?,python,Python,我一直在尝试编写一个应用程序来运行子流程,并(除其他外)在GUI中显示它们的输出,并允许用户单击按钮取消它们。我开始这样的过程: queue = Queue.Queue(500) process = subprocess.Popen( command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) iothread = threading.Thread( target=simple_io_thread,
queue = Queue.Queue(500)
process = subprocess.Popen(
command,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
iothread = threading.Thread(
target=simple_io_thread,
args=(process.stdout, queue))
iothread.daemon=True
iothread.start()
其中简单io线程定义如下:
def simple_io_thread(pipe, queue):
while True:
line = pipe.readline()
queue.put(line, block=True)
if line=="":
break
这很有效。在我的UI中,我定期从队列中执行非阻塞“get”。但是,当我想要终止子流程时,我的问题就出现了。(子进程是一个任意进程,不是我自己写的。)我可以使用terminate方法来终止进程,但我不知道如何保证我的I/O线程将终止。它通常会阻塞管道上的I/O。在我终止流程后的某段时间内,这可能会结束,也可能不会结束。(如果子进程产生了另一个子进程,我可以杀死第一个子进程,但第二个子进程仍将保持管道打开。我甚至不知道如何让这样的子进程干净地终止。)之后,I/O线程将尝试将输出排队,但我不想承诺无限期地从队列中读取
理想情况下,我希望有某种方法来请求终止子进程,在短时间内阻塞(在终止进程的代码中,您也可以显式地
os.close()
线程正在读取的管道?我知道这是一篇老文章,但如果它仍然对任何人都有帮助,我认为您的问题可以通过将subprocess.Popen实例传递给io_线程而不是它的输出流来解决。
如果这样做,则可以将while True:
行替换为while process.poll()==None:
检查子流程返回代码;如果流程尚未完成,则没有返回代码(即process.poll()==None
)。然后,如果line==”:break,则可以删除
我来这里是因为我今天写了一个非常类似的脚本,我得到了这些:-
IOError:close()在对同一文件对象执行并发操作时被调用。
错误。
同样,如果有帮助,我认为我的问题源于(我的)io_线程执行了一些过于高效的垃圾收集,并关闭了我给它的文件句柄(我可能错了,但它现在工作了…)我的不同之处在于它不是守护进程,它通过subprocess.stdout进行迭代,而不是使用while循环..即:-
def io_thread(subprocess,logfile,lock):
for line in subprocess.stdout:
lock.acquire()
print line,
lock.release()
logfile.write( line )
我可能还应该提到,我将bufsize参数传递给subprocess.Popen,以便对其进行行缓冲。这可能已经足够老了,但对来自搜索引擎的人仍然有用
它显示该消息的原因是,在子进程完成后,它关闭了文件描述符,因此,守护进程线程(并发运行)将尝试使用这些关闭的描述符来引发错误
my_thread.join()
print my_thread.is_alive()
my_popen.communicate()
通过在子进程wait()或communicate()方法之前加入线程,应该足以抑制错误
my_thread.join()
print my_thread.is_alive()
my_popen.communicate()
您应该关闭写入管道…但是在编写代码时,您无法访问它。要执行此操作,您应该
用板条箱装烟斗
将写入管道文件id传递给Popen
的stdout
使用读取管道文件simple\u io\u thread
读取行
现在可以关闭写入管道,读取线程将正常关闭
queue = Queue.Queue(500)
r, w = os.pipe()
process = subprocess.Popen(
command,
stdout=w,
stderr=subprocess.STDOUT)
iothread = threading.Thread(
target=simple_io_thread,
args=(os.fdopen(r), queue))
iothread.daemon=True
iothread.start()
现在
os.close(w)
您可以关闭管道,iothread
将毫无例外地关闭。调用process.stdout.close()抛出:IOError:close()在对同一文件对象执行并发操作期间调用。调用os.close(process.stdout.fileno())似乎可以工作,但在丢弃进程时出现异常:文件对象析构函数中的关闭失败:IOError:[Errno 9]错误的文件描述符至少有一个人认为它有用!
my_thread.join()
print my_thread.is_alive()
my_popen.communicate()
queue = Queue.Queue(500)
r, w = os.pipe()
process = subprocess.Popen(
command,
stdout=w,
stderr=subprocess.STDOUT)
iothread = threading.Thread(
target=simple_io_thread,
args=(os.fdopen(r), queue))
iothread.daemon=True
iothread.start()
os.close(w)