Python cmodules prematurely unloaded?

Tim Peters tim_one at email.msn.com
Tue May 25 01:42:26 EDT 1999


[Stuart I Reynolds]
> I'm writing Python wrappers for some C code I have. I've come across a
> problem which seems to be due to Python unloading modules before I'm
> finished with them:

Not quite.  See the thread containing

    http://www.deja.com/getdoc.xp?AN=387135387

> --------------
> import PyGridc #c library functions
>
> class MyClass:
>     def __init__(self)
>         ...
>
>         #datacstruct assumes ownership of
>         #data, calling INCREF
>         self.datacstruct = PyGridc.newGridData( ..some objects.. )
>
>     def __del__(self):
>         print '>>>>>>>>>'
>         print PyGridc
>
>         #Calls DECREF for stored data in struct
>         PyGridc.deleteGridData(self.datacstruct)
>         print '<<<<<<<'
>
> g = MyClass()
> del g
> ------------
>
> All works fine if I keep the "del g" line.

Right.  The problem can occur only at system shutdown time, as Python runs
around deleting all objects bound to module global names; since this brute
force deletion isn't triggered by refcounts reaching 0 (indeed, if an object
is still alive at shutdown time, its refcount *can't* be 0!), there's really
no clue about which order they should be deleted.  So Python deletes objects
bound to module globals in a convenient but more-or-less arbitrary order,
and rebinds the names to None as it goes along.

> However, if I remove just that line

Which means g.__del__ won't get called until some "random" time in the
shutdown sequence.

> and let Python delete it. I get:
>
> %>>>>>>>>>
> %None
> %Exception exceptions.AttributeError: "'None' object has no attribute
> %'deleteGridData'" in <method MyClass.__del__ of MyClass instance at
> %b9d68> ignored

And "exception ... ignored" appears only during shutdown exceptions.
PyGridc was a name in your module's globals, and it happened to get rebound
to None before g got nuked.  So g.__del__ can't reference it successfully.

Easiest workaround is to redefine __del__ as e.g.

    def __del__(self, deleteGridData=PyGridc.deleteGridData):
        deleteGridData(self.datacstruct)

Then the __del__ body doesn't have to do any lookups in any module's
globals, so it won't see any Nones during shutdown.  That usually suffices.
If PyGridc were a Python module, though, you'd also have to make sure that
its deleteGridData function didn't reference anyone's globals either.

when-nobody-volunteers-to-die-death-flips-a-coin-ly y'rs  - tim

RIP Owen "I am your King! You love me!" Hart






More information about the Python-list mailing list