【问题标题】:Tkinter says "Not responding" when running a long subprocess运行长子进程时,Tkinter 说“没有响应”
【发布时间】:2021-03-06 15:14:56
【问题描述】:

我的 tkinter GUI (python 2.7) 启动了一个可以运行很长时间的子进程,我使用 PIPE 将打印语句发送到文本小部件。它可以在没有任何打印语句的情况下运行很长时间,并且 GUI 窗口显示“无响应”,而我在该窗口中无能为力。

#lauch main
proc = subprocess.Popen(["python", testPath, filePath] + script_list,
                        stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=0)

#send the scripts output to the GUI text box
for line in iter(proc.stdout.readline,''):
    text.insert(END, line)
    #update in "real time"
    text.see(END)
    root.update()
    text.update_idletasks()

尝试在子进程中添加 printflush 语句,但这没有帮助。

【问题讨论】:

  • 读过那篇文章,但不知道它对我有什么帮助。谢谢!
  • 尝试使用threading
  • 需要进一步阅读。这是 subprocess.Popen 的替代品吗?
  • 您不能在 tkinter 应用程序中执行阻止 mainloop() 运行的操作,因此很可能是 proc.stdout.readline 阻止了它。

标签: python python-2.7 tkinter subprocess


【解决方案1】:

以下示例是否为您提供了从子进程读取输出的方法?

import threading
from tkinter import  *
import subprocess
import time

class SubprocessThread(threading.Thread):
    def __init__(self, widget):
        threading.Thread.__init__(self)
        self.widget = widget
        self.stopEvent = threading.Event()
        print("Task Initialised")
    def run(self):
        print("Task Running")
        startupinfo = subprocess.STARTUPINFO()
        startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
        proc = subprocess.Popen(["ping", "-n", "8", "8.8.8.8"],
                        stdout=subprocess.PIPE, stderr=subprocess.STDOUT, bufsize=0, startupinfo=startupinfo)
        
        for line in iter(proc.stdout.readline,''):
            if self.stopEvent.is_set():
                break
            self.widget.insert('end',line.decode())
            time.sleep(0.1)
        self.widget.insert('end',"\n\nComplete")



def startTask():
    task.start()

def stopTask():
    task.stopEvent.set()
            
        
gui = Tk()

text = Text(gui,width=80)
text.pack()


button1 = Button(gui, text='Start Process', fg='white', bg='gray', height=2, width=9, command=startTask)
button1.pack()

button2 = Button(gui, text='Stop Process', fg='white', bg='gray', height=2, width=9, command=stopTask)
button2.pack()



# start the GUI
task = SubprocessThread(text)

gui.mainloop()

这将创建一个单独的线程,该线程将“侦听”来自被调用进程的新标准输出。在本例中,我只调用 ping。

请注意,使用子进程调用另一个 python 脚本通常是不好的做法。为什么不直接调用该脚本中的函数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    • 2013-01-17
    • 1970-01-01
    • 2016-01-10
    • 2021-10-07
    • 2012-12-14
    相关资源
    最近更新 更多