[Python-Dev] AtExit Functions

M.-A. Lemburg mal@lemburg.com
Tue, 16 Jul 2002 09:57:41 +0200


Tim Peters wrote:
> [MAL, on Py_AtExit()]
> 
>>PyObject_Del() [must be avoided] as well ?
> 
> 
> I don't think that one's a problem.  The Py{Object,Mem}_{Del,DEL,Free,FREE}
> spellings have resolved to plain free().  Under pymalloc that's different,
> but pymalloc never tears itself down so it's safe there too.

Good, because I've been using that particular API for years
in Py_AtExit() functions.

>>>We have two sets of exit-function gimmicks, one that runs at
>>>the very start of Py_Finalize(), and the other at the very end.
>>>If you need to clean up Python objects, you have to get into
>>>the first group.
>>
> 
>>I suppose the first one is what the atexit module exposes
>>in Python 2.0+, right ?
> 
> 
> Yes, but do read Skip's message too.  atexit.py wraps a primitive gimmick
> that was also in 1.5.2.  See the docs for sys.exitfunc at
> 
>     http://www.python.org/doc/1.5.2p2/lib/module-sys.html
> 
> The docs are pretty much the same now, except atexit.py provides a rational
> way to register multiple exit functions now. 

The problem is not finding code to work in Python 1.5.2.
I have my own ExitFunctions.py module which did pretty much
the same as atexit.py for Python 1.5.2. The problem is that
if there's no standard for managing atexit functions available
in Python 1.5.2, then it is likely that others will have used
a similar method and maybe failed to play nice with other
such hooks.

> Hmm!  The logic in atexit.py
> looks wrong if sys.exitfunc already exists:  then atexit appends it to the
> module's own list of exit functions, but then forgets to do anything to
> ensure that its own list gets run at the end.  I conclude that nobody has
> tried mixing these gimmicks.

Indeed.

try:
     x = sys.exitfunc
except AttributeError:
     sys.exitfunc = _run_exitfuncs
else:
     # if x isn't our own exit func executive, assume it's another
     # registered exit function - append it to our list...
     if x != _run_exitfuncs:
         register(x)

The logic seems a bit wrong for that case: how could
x possibly be _run_exitfuncs ? I think this code should
look something like this:

try:
     x = sys.exitfunc
except AttributeError:
     pass
else:
     # if x isn't our own exit func executive, assume it's another
     # registered exit function - append it to our list...
     register(x)
sys.exitfunc = _run_exitfuncs

> In any case, you can do something safe across all versions via:
> 
> import sys
> try:
>     inherited = sys.exitfunc
> except AttributeError:
>     def inherited():
>         pass
> 
> def myexitfunc():
>     clean_up_my_stuff()
>     inherited()
> 
> sys.exitfunc = myexitfunc
> del sys
> 
> You can get screwed then if somebody else sets sys.exitfunc later without
> being as considerate of your hook as the code above is of a pre-existing
> hook, but then that's why atexit.py was created and you should move to a
> later Python if you want saner behavior <wink>.

Right. OTOH, if someone screws up here, worst which can happen
is a memory leak. Not all that much too lose nowadays with GB of
RAM ;-)

>>The problem with that approach is that there may still be some
>>references to objects left in lists and dicts which are cleaned
>>up after having called the atexit functions. This is not so
>>much a problem in my cases, but something to watch out in other
>>applications which use C level Python objects as globals.
> 
> 
> I don't know specifically what you have in mind there, but I expect that it
> would kick off another round of the every-18-months discussion of what kind
> of module finalization protocol Python should start to support.  A PEP for
> that is long overdue.
 >
>>>>Also, atexit.py is not present in Python 1.5.2.
>>>
> 
>>>What's that <wink>?
>>
> 
>>That's the Python version which was brand new just 3 years
>>ago. I know... in US terms that's for history books ;-)
> 
> 
> Oh, 3 years ago is sooooo 20th century!  Goodness, they didn't even have
> cellophane sleeping tubes back then.  May as well go back to worshipping
> cats while you're at it.

Naa, I'll stick to the Python 1.2 tutorial I still keep under
my pillow as per instructions from Guido at the time.

-- 
Marc-Andre Lemburg
CEO eGenix.com Software GmbH
_______________________________________________________________________
eGenix.com -- Makers of the Python mx Extensions: mxDateTime,mxODBC,...
Python Consulting:                               http://www.egenix.com/
Python Software:                    http://www.egenix.com/files/python/