为啥 tkinter 不能很好地处理多处理?

Posted

技术标签:

【中文标题】为啥 tkinter 不能很好地处理多处理?【英文标题】:Why doesn't tkinter play nicely with multiprocessing?为什么 tkinter 不能很好地处理多处理? 【发布时间】:2012-06-01 02:36:17 【问题描述】:

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

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,可以通过在内部导入tkinter 来修复它函数f,并且问题发生在Linux而不是Solaris。

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

【问题讨论】:

-0。你知道问题所在。您知道已提交错误报告。你知道解决方法。唯一的另一个主要问题是“任何其他模块在多处理方面也有类似的问题吗?”,这似乎有点开放式。 @StevenRumbalski:我不知道问题所在——我不知道 tkinter 在做什么而无法在这里工作,或者为什么它依赖于平台。该错误报告是在 3 年前提交的,没有迹象表明有人知道为什么(或在什么条件下)会发生这种情况或如何修复它。也许我的最后一个问题应该是“是否有任何其他标准库模块在 fork 进程之前无法导入”,这更具体一些。 【参考方案1】:

截至 2013 年 9 月,错误报告中还有一些额外的 cmets,可以更深入地了解实际问题。

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

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

【讨论】:

【参考方案2】:

我怀疑问题与与 X 服务器的连接(通常是套接字)有关。如果这是在进程为fork()-ed 之前创建的,则子进程继承此连接。但是如果它试图使用它,X 服务器就会变得混乱。

粗略查看Tkinter.py 之后,看起来可能在开始进程之前调用NoDefaultRoot 函数可能有用。这完全取决于何时与 X 服务器建立连接。

否则在分叉之后导入 Tkinter 似乎是可行的方法。

【讨论】:

以上是关于为啥 tkinter 不能很好地处理多处理?的主要内容,如果未能解决你的问题,请参考以下文章

Plotly 不能很好地处理条形图的 NA。我该在哪里解决这个问题?

通过 talend 从 oracle 加载到 greenplum 时的数据不能很好地处理 CLOB 列

NLTK 正则表达式标记器在正则表达式中不能很好地处理小数点

Python:在使用多处理时更新 Tkinter

为啥 Parallel::ForkManager 创建子进程很好,但不能并行处理它们

为啥所有 Active Record 都讨厌? [关闭]