【问题标题】:python tkinter window going unresponsive and hangingpython tkinter窗口无响应并挂起
【发布时间】:2017-08-24 13:26:57
【问题描述】:
MyButton1 =Button(master, text='Quit',bg="grey",width=20, 
command=master.quit)
MyButton1.place(x=200, y=100)
MyButton2 =Button(master, text='Propagate', bg="grey",width=20, 
command=mainmethod)
MyButton2.place(x=1000, y=100)
master.geometry("1500x1500")
master.mainloop( )

在上面的代码中,按下传播按钮后 mainmethod 正在调用.. 我在 main 方法中编写了我的逻辑,其中仅此方法需要 2 分钟执行,同时 GUI 进入无响应状态几分钟,然后在我插入的文本框中显示我所有需要的输出

除了使用多线程之外,是否还有办法避免无响应的问题

我希望在按下传播按钮后按钮应该被禁用并且窗口不应该无响应并连续显示我在 main 方法中添加的 text.insert 语句?????

【问题讨论】:

  • 如果你不喜欢多线程,那么多处理呢?
  • 但是我在 main 方法中编写的逻辑应该是顺序的,我可以使用多处理吗?请您详细说明一下,谢谢提前

标签: python python-2.7 tkinter tkinter-canvas


【解决方案1】:

为了防止挂起,你需要将mainmethod 中的计算与 Tkinter 的主循环分开,方法是在不同的线程中执行它们。但是,由于 GIL(全局解释器锁),Python 中的线程系统不像其他语言(AFAIK)那样发达,但是有一种替代方法 - 使用像线程一样的进程。 multiprocessing 库可以做到这一点。

为了防止挂起,你可以创建另一个函数

from multiprocessing import Process
def mainmethodLaunch():
    global mainmethodProcess
    mainmethodProcess = Process(target=mainmethod)
    mainmethodProcess.start()

并将此函数绑定到MyButton2 而不是mainmethod 本身。

文档:https://docs.python.org/2/library/multiprocessing.html#the-process-class

您可以在示例中看到p.joinjoin 方法将导致您的主进程等待另一个完成,这是您不希望的。

所以当你按下按钮时,mainmethodLaunch 函数将被调用,它会创建另一个执行mainmethod 的进程。 mainmethodLaunch 函数自己的运行持续时间应该是微不足道的。由于使用了另一个进程,Tkinter 窗口不会挂起。但是,如果您这样做,您将无法与 mainmethod 进程在工作期间进行任何形式的交互。

为了让这些进程相互通信,您可以使用管道 (https://docs.python.org/2/library/multiprocessing.html#exchanging-objects-between-processes) 我想这个例子很清楚。

为了随着时间的推移从mainmethod 进程接收一些数据,您将不得不轮询parent_conn 一次,比方说,第二次。这可以通过 Tkinter 的 after 方法来实现 (tkinter: how to use after method)

重要提示:使用multiprocessing 时,您必须在if __name__ == '__main__': 块中初始化程序。我的意思是,在函数和这个块之外不应该有做某事的代码,不应该有零缩进的做某事代码。

这是因为multiprocessing 将分叉同一个 Python 可执行文件,它必须区分主进程和分叉的进程,而不是在分叉的进程中进行初始化。

如果你这样做了,请检查两次,因为如果你犯了这样的错误,它可能会让你不仅挂起 Tkinter 窗口,还挂起整个系统 :) 因为该进程将无休止地分叉自己,消耗你所有的内存,不管你有多少。

【讨论】:

  • 但是如果我想更新文本框(在 if name == 'main':) 如下 def mainmethod: ..... txt.insert(1.0,"some print ") ...... 我得到了 Traceback (最近一次调用最后): 文件 "setup.py",第 366 行,在 master.mainloop() 文件 "C:\CRMAPPS\APPS\PYTHON262\lib\lib-tk\Tkinter.py",第 1017 行,在 mainloop self.tk.mainloop(n) 是否对象 txt可以作为输入传递给进程吗?请帮帮我
  • 正如我所说,您需要在 mainmethod 进程和 Tkinter 应用程序之间建立管道连接。 Mainmethod 必须通过管道发送要打印的行,并且 Tkinter 应用程序必须轮询该管道以打印传入的行。您将无法直接从 mainmethod 操作 Tkinter 窗口,这是使用另一个进程的代价。
  • @saikiranvura 哦,函数定义必须在if __name__ == '__main__':块之外
  • 谢谢 Andrew Cherevatkin 我会试试的
猜你喜欢
  • 2014-02-26
  • 1970-01-01
  • 2021-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-21
  • 1970-01-01
相关资源
最近更新 更多