gpt4 book ai didi

python - 如何运行子进程,在 GUI 中显示其输出并允许其终止?

转载 作者:太空宇宙 更新时间:2023-11-03 13:53:57 25 4
gpt4 key购买 nike

我一直在尝试编写一个运行子进程的应用程序,并且(除其他外)在 GUI 中显示它们的输出,并允许用户单击一个按钮来取消它们。我开始这样的过程:

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()

其中simple_io_thread定义如下:

def simple_io_thread(pipe, queue):
while True:
line = pipe.readline()
queue.put(line, block=True)
if line=="":
break

这很好用。在我的用户界面中,我定期从队列中进行非阻塞“获取”。但是,当我想终止子进程时,我的问题就来了。 (子进程是任意进程,不是我自己写的。)我可以使用terminate方法终止进程,但我不知道如何保证我的I/O线程会终止。它通常会在管道上执行阻塞 I/O。在我终止进程后,这可能会或可能不会结束一段时间。 (如果子进程产生了另一个子进程,我可以杀死第一个子进程,但第二个子进程仍将保持管道打开。我什至不确定如何让这样的孙子进程干净地终止.) 之后,I/O 线程将尝试将输出排入队列,但我不想无限期地 promise 从队列中读取。

理想情况下,我想要一些方法来请求终止子进程,阻塞一小段时间(<0.5 秒),然后保证 I/O 线程已经退出(或将及时退出而无需干扰其他任何事情)并且我可以停止从队列中读取数据。

解决方案使用 I/O 线程对我来说并不重要。如果有另一种方法可以在 Windows 和 Linux 上使用 Python 2.6 和 Tkinter GUI 执行此操作,那会很好。


编辑——Will 的回答和我在网上看到的关于用其他语言执行此操作的其他事情表明操作系统希望您只关闭主线程上的文件句柄,然后 I/O 线程应该出来它的阻塞读取。但是,正如我在评论中所述,这似乎对我不起作用。如果我在主线程上这样做:

process.stdout.close()

我得到:

IOError: close() called during concurrent operation on the same file object.

...在主线程上。如果我在主线程上这样做:

os.close(process.stdout.fileno())

我得到:

close failed in file object destructor: IOError: [Errno 9] Bad file descriptor

...稍后在主线程中尝试关闭文件句柄本身。

最佳答案

我知道这是一篇旧文章,但如果它仍然对任何人有帮助,我认为您的问题可以通过将 subprocess.Popen 实例传递给 io_thread 而不是它的输出流来解决。如果这样做,则可以将 while True: 行替换为 while process.poll() == None:

process.poll()检查子进程返回码;如果进程尚未完成,则没有进程(即 process.poll() == None)。然后您可以取消 if line == "": break

我来这里的原因是因为我今天写了一个非常相似的脚本,我得到了那些:-
IOError: close() 在对同一文件对象进行并发操作时调用。 错误。

同样,如果它有帮助,我认为我的问题源于(我的)io_thread 进行了一些过于高效的垃圾收集,并关闭了我给它的文件句柄(我可能错了,但它现在可以工作了..) 我的不同之处在于它不是守护进程,它遍历 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,因此它是行缓冲的。

关于python - 如何运行子进程,在 GUI 中显示其输出并允许其终止?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1433367/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com