"The c++ part has been deleted" message using atexit

Hey list,
I'm using atexit to cancel a repeating timer in my GUI. I'm using it
in other modules as well for various things. I just started setting
this up, because I was getting thread exceptions when I closed the
program. The problem is that something isn't working, and it looks
worse than the thread exceptions did. Now, when I close my
application, I'm seeing this error when my onExit function tries to
cancel that timer:
"wx._core.PyDeadObjectError: the C++ part of the JobsListManager
object has been deleted. Attribute access no longer allowed."

I imagine this is something to do with the program having already
removed the GUI object, as the error suggests, but I'm not sure how to
get around it. I register the function in my __init__ method for my
JobsListManager class:
atexit.register(self.onExit)
As mentioned, I'm using atexit in another module, and will likely
include it in a few more soon. I'm just not seeing where I went wrong
with this one. TIA for any help!

I usually:

  import wx
  ...
  execute lots of code
  ...

  def onExit():
    try:
      tada
    except wx._core.PyDeadObjectError, e:
      log.whine('cannot shutdown timer, %s', e)
    go forth ...

or some such.

Karsten

···

On Mon, Feb 01, 2016 at 08:09:09AM -0500, Alex Hall wrote:

I'm using atexit to cancel a repeating timer in my GUI. I'm using it
in other modules as well for various things. I just started setting
this up, because I was getting thread exceptions when I closed the
program. The problem is that something isn't working, and it looks
worse than the thread exceptions did. Now, when I close my
application, I'm seeing this error when my onExit function tries to
cancel that timer:
"wx._core.PyDeadObjectError: the C++ part of the JobsListManager
object has been deleted. Attribute access no longer allowed."

I imagine this is something to do with the program having already
removed the GUI object, as the error suggests, but I'm not sure how to
get around it. I register the function in my __init__ method for my
JobsListManager class:
atexit.register(self.onExit)
As mentioned, I'm using atexit in another module, and will likely
include it in a few more soon. I'm just not seeing where I went wrong
with this one. TIA for any help!

--
GPG key ID E4071346 @ eu.pool.sks-keyservers.net
E167 67FD A291 2BEA 73BD 4537 78B9 A9F9 E407 1346

Thanks for the suggestion, but I'm now getting the exact same error on
the line where I log the exception. Besides, logging the problem still
means the core problem--something is gone, so my timer can't be
stopped--is still there.

···

On 2/1/16, Karsten Hilbert <Karsten.Hilbert@gmx.net> wrote:

On Mon, Feb 01, 2016 at 08:09:09AM -0500, Alex Hall wrote:

I'm using atexit to cancel a repeating timer in my GUI. I'm using it
in other modules as well for various things. I just started setting
this up, because I was getting thread exceptions when I closed the
program. The problem is that something isn't working, and it looks
worse than the thread exceptions did. Now, when I close my
application, I'm seeing this error when my onExit function tries to
cancel that timer:
"wx._core.PyDeadObjectError: the C++ part of the JobsListManager
object has been deleted. Attribute access no longer allowed."

I imagine this is something to do with the program having already
removed the GUI object, as the error suggests, but I'm not sure how to
get around it. I register the function in my __init__ method for my
JobsListManager class:
atexit.register(self.onExit)
As mentioned, I'm using atexit in another module, and will likely
include it in a few more soon. I'm just not seeing where I went wrong
with this one. TIA for any help!

I usually:

  import wx
  ...
  execute lots of code
  ...

  def onExit():
    try:
      tada
    except wx._core.PyDeadObjectError, e:
      log.whine('cannot shutdown timer, %s', e)
    go forth ...

or some such.

Karsten
--
GPG key ID E4071346 @ eu.pool.sks-keyservers.net
E167 67FD A291 2BEA 73BD 4537 78B9 A9F9 E407 1346

--
You received this message because you are subscribed to the Google Groups
"wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to wxpython-users+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Likely, when logging the exception instance the logging code
tries again to access some wx part that's already gone.

Tried "log.whine('cannot shutdown timer')" instead ?

If that doesn't help you'll have to show more of what's actually happening.

Karsten

···

On Mon, Feb 01, 2016 at 08:28:20AM -0500, Alex Hall wrote:

Thanks for the suggestion, but I'm now getting the exact same error on
the line where I log the exception.

--
GPG key ID E4071346 @ eu.pool.sks-keyservers.net
E167 67FD A291 2BEA 73BD 4537 78B9 A9F9 E407 1346

No, still nothing. I'm not sure what code will help; this isn't a big
application, but it's not one or two files either. For now, here's a
condensed version of my GUIManager.py file:

#import stuff

logger = logging.getLogger(globals.appName+"."+__name__)

class ListManager(wx.Panel):
def __init__(self,
   #a bunch more parameters
  ):
  super(ListManager, self).__init__(parent)

  self.logger = logging.getLogger(globals.appName+"."+__name__+"."+title)
  self.logger.debug("Initializing.")
  #a bunch more setup

def setUpGUI(self):
  raise NotImplementedError

#a couple more methods

class JobsListManager(ListManager):
def __init__(self,
   #yet more parameters
  ):
  #do more setup, then:

  atexit.register(self.onExit)

  super(JobsListManager, self).__init__( parent, title, choices,
columnHeaders, showAddButton, addButtonLabel, showEditButton,
editButtonLabel, showDeleteButton, deleteButtonLabel)

def setUpGUI(self):
  #a bunch of setup, then:
  self.nextRunDisplayTimesUpdateTimer.start()

#methods and more methods...

def onExit(self):
  try:
   self.nextRunDisplayTimesUpdateTimer.stop()
  except wx._core.PyDeadObjectError, e:
   self.logger.error("Error cancelling timeToNextRun update timer.")

I don't know if that's what you wanted, or if more code would help? If
it matters, this all gets kicked off in main.py, which calls initGUI
in GUIManager.py, which creates these ListManager objects and adds
them to a notebook in a frame.

···

On 2/1/16, Karsten Hilbert <Karsten.Hilbert@gmx.net> wrote:

On Mon, Feb 01, 2016 at 08:28:20AM -0500, Alex Hall wrote:

Thanks for the suggestion, but I'm now getting the exact same error on
the line where I log the exception.

Likely, when logging the exception instance the logging code
tries again to access some wx part that's already gone.

Tried "log.whine('cannot shutdown timer')" instead ?

If that doesn't help you'll have to show more of what's actually happening.

Karsten
--
GPG key ID E4071346 @ eu.pool.sks-keyservers.net
E167 67FD A291 2BEA 73BD 4537 78B9 A9F9 E407 1346

--
You received this message because you are subscribed to the Google Groups
"wxPython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to wxpython-users+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Oh, OK, you are registering a _member_ function of a wx.Panel
to be run at exit. By the time the atexit hook is run the
wx.Panel instance will have been destroyed already.

You'll have to register a (sufficiently) global function to
be run. When you create the timer you'd have to bind it to a
global reference variable, too, such that the global function
can use that to shutdown the timer.

I hope that'll work out :slight_smile:

Karsten

···

On Mon, Feb 01, 2016 at 09:05:09AM -0500, Alex Hall wrote:

No, still nothing. I'm not sure what code will help; this isn't a big
application, but it's not one or two files either. For now, here's a
condensed version of my GUIManager.py file:

#import stuff

logger = logging.getLogger(globals.appName+"."+__name__)

class ListManager(wx.Panel):
def __init__(self,
   #a bunch more parameters
  ):
  super(ListManager, self).__init__(parent)

  self.logger = logging.getLogger(globals.appName+"."+__name__+"."+title)
  self.logger.debug("Initializing.")
  #a bunch more setup

def setUpGUI(self):
  raise NotImplementedError

#a couple more methods

class JobsListManager(ListManager):
def __init__(self,
   #yet more parameters
  ):
  #do more setup, then:

  atexit.register(self.onExit)

  super(JobsListManager, self).__init__( parent, title, choices,
columnHeaders, showAddButton, addButtonLabel, showEditButton,
editButtonLabel, showDeleteButton, deleteButtonLabel)

def setUpGUI(self):
  #a bunch of setup, then:
  self.nextRunDisplayTimesUpdateTimer.start()

#methods and more methods...

def onExit(self):
  try:
   self.nextRunDisplayTimesUpdateTimer.stop()
  except wx._core.PyDeadObjectError, e:
   self.logger.error("Error cancelling timeToNextRun update timer.")

--
GPG key ID E4071346 @ eu.pool.sks-keyservers.net
E167 67FD A291 2BEA 73BD 4537 78B9 A9F9 E407 1346