7

以下代码在 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 但不是索拉里斯。

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

4

2 回答 2

0

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

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

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

于 2013-09-29T19:01:50.510 回答
0

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

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

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

于 2012-09-01T23:08:40.290 回答