Reputation: 99
My application has been failing on OSX when using multiprocessing and tkinter. The minimum example is as easy as follows:
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()
When trying to execute this snippet mac fails with the following report:
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
Deleting the Spinbox import (not used in the code) makes everything run. The same problem appears on python 3.4.4 and 2.7 (changing tkinter to Tkinter)
Removing the multiprocessing module and making everything run on the same process also makes the problem disappear.
My guess is that I'm violating some Tk/Tcl constrain, but I haven't found anything reading the docs about this, also the fact that this only happens with Spinbox and not with Entry or other widgets is suspicious.
Upvotes: 1
Views: 416
Reputation: 99
I managed to make it work, for some reason tkinter wants to be imported in the same Thread/Process that its executing from.
When extending multiprocess.Proccess the new process code is inside the run() method, the init is executed on the parent process. Therefore changing all the imports to be locally done on the run method fixes the problem.
The example code looks as follows:
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()
Now my application works on Windows, Linux and Mac.
Upvotes: 1
Reputation: 19184
When I run your code from IDLE editor, on Windows, there is no error, but no tk box either, just the '>>>' prompt in Shell. When I put the end of the code under an if name clause, as specific in the multiprocessing doc
if __name__ == '__main__':
g = Gui()
g.start()
a tk box appears. The same is true with only g.start()
so protected. Try one or both versions on your Mac. I don't know if this is the only problem on OSX, but it will at least let you start with something that runs on other systems.
Upvotes: 0