Abstracting try..finally with generators (instead of macros)

Andrew Dalke adalke at mindspring.com
Mon Dec 16 13:32:11 EST 2002


Beni Cherniavsky wrote:
> While modules are generally not involved in cycles (except when there are
> mutually recursive imports), a module's dictionary generally is involved
> in a cycle because every function and method defined in the module
> references its __dict__, and these functions and methods are generally
> reachable from that __dict__. Thus, when a module is deleted, I explicitly
> clear its __dict__ carefully. (This has always been done, just not
> "carefully".)


> `sys.stdout` served just as an example in my code.  Besides, as said
> above, you never should worry in Python about functions becoming orphans -
> the module's __dict__ can't get deleted as long as the function lives.

I'm sorry.  I haven't put enough time into this to explain myself
properly.

I've had this be the case.  I have a C extension called 
'dayswig_python'.  It contains two functions, dt_alloc_mol() and
dt_dealloc().   I made a wrapper like this:

import dayswig_python

class Molecule:
   def __init__(self):
     self.mol = dayswig_python.dt_alloc_mol()
   def __del__(self):
     dayswig_python.dt_dealloc(self.mol)

Call this module 'daylight'.  Now instantiate a Molecule and
exit Python

import daylight
mol = Dayight.Molecule()


The __main__, daylight, and dayswig_python modules can be cleared
in arbitrary order.  Suppose dayswig_python is cleared first.
Then when mol's finalizer is called, dayswig_python contains
nothing so the getattr for dayswig_python.dt_dealloc fails with
an AttributeError.

I know this happens.  'mol' doesn't have a reference to
'dayswig_python'.  The __del__ does a global (in-module) lookup
for that module in the finalizer, based on the string name.
So the module cleanup code doesn't know there are functions
which might still use functions in the module.

You said:
 > because every function and method defined in the module
 > references [the module's] __dict__,

This is not the case.  Rather, if it is, please show me
how to get to the module's global namespace via a gettattr
chain.  (globals() will work, but I don't know how it works.)

					Andrew
					dalke at dalkescientific.com




More information about the Python-list mailing list