Search code examples
wxpython

Hanging issue on closing GUI


When I close the GUI I have developed, there is some hanging in the Terminal (on Mac OS X Mavericks), as opposed to the almost instantaneous termination on the Terminal that is expected with the closing of the GUI from the enduser's side. When it does close in the Terminal the following message appears:

Checking Connection to Server...
Connection Failed!
Exception in thread Thread-3:
Traceback (most recent call last):
  File       "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 810, in __bootstrap_inner
    self.run()
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 1082, in run
    self.function(*self.args, **self.kwargs)
  File "sigd_tool_v20.py", line 1751, in CheckConnection
    self.connect.SetLabel("Not Connected!")
  File "/usr/local/lib/wxPython-3.0.0.0/lib/python2.7/site-packages/wx-3.0-osx_cocoa/wx/_core.py", line 16712, in __getattr__
raise PyDeadObjectError(self.attrStr % self._name)
PyDeadObjectError: The C++ part of the TestPanel object has been deleted, attribute access no longer allowed.

I have included a function in the GUI called CheckConnection that allows the enduser to see whether or not they are still connected to our server as they are using the GUI. I suspect this is due to improper threading, largely because of what the Terminal indicates. I don't understand why I would be getting the PyDeadObjectError though. Any ideas for me? Thank you in advance!


Solution

  • The thread is probably accessing the GUI directly, which is something you definitely shouldn't be doing. You can only access the GUI with wxPython's thread-safe methods: wx.CallAfter and wx.PostEvent.

    The PyDeadObjectError means that something (probably the thread) is trying to access the TestPanel after it's already been destroyed.

    When you close the application, you will need to end the thread BEFORE you close the frame. That means you need to either call the thread's join() method or kill it some other way. Once that's done, you can close the frame normally.