为什么 tkinter 不能很好地处理多处理?

2022-01-12 00:00:00 python tkinter multiprocessing

问题描述

以下代码在linux中的python 3.2.2中没有做任何事情就挂起:

The following code hangs without doing anything in python 3.2.2 in linux:

import tkinter
from multiprocessing import Process

def f():
    root = tkinter.Tk()
    label = tkinter.Label(root)
    label.pack()
    root.mainloop()

p = Process(target=f)
p.start()

我找到的关于这个问题的唯一信息是 issue 5527,其中指出问题出在 tkinter 在进程被分叉之前被导入,可以通过在函数 f 中导入 tkinter 来修复,并且该问题在 Linux 中出现但不是索拉里斯.

The only information I have found about this problem is issue 5527, in which it is noted that the problem is with tkinter being imported before the process is forked, that it can be fixed by importing tkinter inside the function f, and that the problem occurs in Linux but not Solaris.

有谁知道究竟是什么导致了这个问题,是故意的还是最终会得到解决?除了在我需要的任何地方本地导入 tkinter 之外,还有其他解决方法吗(这看起来很糟糕)?其他模块是否有类似的多处理问题?

Does anyone know what exactly is causing this problem, and if it is intentional or will eventually be fixed? Is there any workaround other than to import tkinter locally everywhere I need it (which seems like bad style)? Do any other modules have similar issues with multiprocessing?


解决方案

截至 2013 年 9 月,有一些关于错误报告的附加评论可以让您更深入地了解实际问题.

As of September 2013, there are some additional comments on the bug report that give more insight into what the actual problem is.

http://bugs.python.org/issue5527#msg194848
http://bugs.python.org/issue5527#msg195480

基于上述情况,我猜测正在发生以下情况:Tkinter 不是线程安全的,因此(无论出于何种原因)Tkinter 想知道哪个线程是主线程.Tkinter 假设加载 Tkinter 模块时的主线程也将是程序执行的主线程.当你在加载 Tkinter 后 fork 或 multiprocess 时,这个假设就被打破了.(例如,fork 后,记住的主线程在父线程,而不是子线程.)

Based on the above, I'm guessing something like the following is happening: Tkinter is not thread safe, so (for whatever reason) Tkinter wants to know which thread is the main thread. Tkinter assumes that the main thread when the Tkinter module is loaded will also be the main thread for program execution. When you fork or multiprocess after loading Tkinter, this assumption is broken. (For example, after a fork, the remembered main thread is in the parent, not the child.)

相关文章