Tkinter Spinbox 和多处理导致 mac SEGFAULT

Tkinter Spinbox and multiprocessing causes mac SEGFAULT

我的应用程序在 OSX 使用多处理和 tkinter 时一直失败。最简单的例子如下:

import multiprocessing
from tkinter import Spinbox #Delete this line and it works

class Gui(multiprocessing.Process):

    def run(self):
        self.start_window()
        self.root.mainloop()

    def start_window(self):
        from tkinter import Tk
        self.root = Tk()
        self.root.title('Test')

g = Gui()
g.start()

尝试执行此代码段时 mac 失败并显示以下报告:

Process: Python [1453] Path: > /Library/Frameworks/Python.framework/Versions/3.4/Resources/Python.app/Contents/MacOS/Python Identifier: Python Version: 3.4.4 (3.4.4) Code Type: X86-64 (Native) Parent Process: Python [1452] Responsible: Terminal [395] User ID: 501

Date/Time: 2016-01-18 18:33:23.281 +0100 OS Version: Mac OS X 10.11.2 (15C50) Report Version: 11 Anonymous UUID: 49081BD5-7C1E-52F6-E5D9-F9F41BA8DFE5

Time Awake Since Boot: 6200 seconds

System Integrity Protection: enabled

Crashed Thread: 0 Dispatch queue: com.apple.main-thread

Exception Type: EXC_BAD_ACCESS (SIGSEGV) Exception Codes: KERN_INVALID_ADDRESS at 0x0000000000000110

VM Regions Near 0x110: --> __TEXT 0000000100000000-0000000100001000 [ 4K] r-x/rwx SM=COW /Library/Frameworks/Python.framework/Versions/3.4/Resources/Python.app/Contents/MacOS/Python

Application Specific Information: * multi-threaded process forked * crashed on child side of fork pre-exec

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread 0 libdispatch.dylib 0x00007fff99f0fd69 _dispatch_async_f_slow + 391

1 libxpc.dylib 0x00007fff8fb8daa0 xpc_connection_resume + 192

2 com.apple.CoreFoundation 0x00007fff9bbb69d1 _CFPrefsWithDaemonConnection + 353

删除 Spinbox 导入(代码中未使用)会使一切变得 运行。同样的问题出现在 python 3.4.4 和 2.7(将 tkinter 更改为 Tkinter)

删除多处理模块并使所有内容 运行 在同一进程上也可以使问题消失。

我的猜测是我违反了一些 Tk/Tcl 约束,但我没有找到任何关于此的文档,而且这只发生在 Spinbox 而不是 Entry 或其他小部件上是可疑的。

当我在 Windows 上从 IDLE 编辑器 运行 你的代码时,没有错误,但也没有 tk 框,只有 Shell 中的“>>>”提示.当我将代码末尾放在 if name 子句下时,如 multiprocessing doc

中所述
if __name__ == '__main__':
   g = Gui()
   g.start()

一个tk框出现。只有 g.start() 如此保护也是如此。在 Mac 上尝试一个或两个版本。我不知道这是否是 OSX 上的唯一问题,但它至少可以让您从其他系统上 运行 的东西开始。

我设法使它工作,出于某种原因,tkinter 希望在执行它的同一个 Thread/Process 中导入。

当扩展 multiprocess.Proccess 新进程代码在 运行() 方法内部时,init 在父进程上执行。因此,将所有导入更改为在 运行 方法上在本地完成可以解决问题。

示例代码如下所示:

import multiprocessing

class Gui(multiprocessing.Process):

    def run(self):
        from tkinter import Spinbox # or Tk, or * ....
        self.start_window()
        self.root.mainloop()

    def start_window(self):
        from tkinter import Tk
        self.root = Tk()
        self.root.title('Test')

g = Gui()
g.start()

现在我的应用程序适用于 Windows、Linux 和 Mac。