Mailing List Archive

any way to know when the program is exiting?
Hi,

I was wondering if there is any way in a __del__ method to know when it's
invoked on the way out, as a result of the program going away?

I have a __del__ method of a class that sends a message to a global variable.
It happens that on the way out, that value in that variable is destroyed before
the __del__ methods of my instances are invoked. The result is that I have a
bogus value that doesn't respond to the usual methods anymore. How can I
prevent sending messages to that object?

A possible solution would be to use atexit() but this doesn't work if the user
program that's using my library replaces it with its own function.

Any ideas?


Thanks,
--
Ovidiu Predescu <ovidiu@cup.hp.com>
http://andromeda.cup.hp.com/ (inside HP's firewall only)
http://www.geocities.com/SiliconValley/Monitor/7464/
any way to know when the program is exiting? [ In reply to ]
Ovidiu Predescu <ovidiu@cup.hp.com> writes:
> I was wondering if there is any way in a __del__ method to know when it's
> invoked on the way out, as a result of the program going away?

AFAIK, not..

> I have a __del__ method of a class that sends a message to a global
> variable. It happens that on the way out, that value in that variable is
> destroyed before the __del__ methods of my instances are invoked. The
> result is that I have a bogus value that doesn't respond to the usual
> methods anymore. How can I prevent sending messages to that object?

Keep reference to the global variable in the classes with __del__.

Example follows: (How I kill child processes, and ensure the os module is
garbage collected _after_ the DelWrapper instance is __del__'d)

class DelWrapper:
"""
quick-n-dirty class to wrap __del__
"""
def __init__(self, f):
self.__del__ = f

def foo():
... # proprietary, super-secret code snipped
global __tmp
__tmp = DelWrapper(lambda k=os.kill,pid=pid:apply(k, (pid, 15)))

> A possible solution would be to use atexit() but this doesn't work if the
> user program that's using my library replaces it with its own function.


> Any ideas?

Occassionally, some ;)

-Markus

--
"I am Grey. I stand between the candle and the star.
We are Grey. We stand between the darkness and the light."
- Delenn / Babylon 5 [ #1 scifi show ATM, IMO ]
any way to know when the program is exiting? [ In reply to ]
Ovidiu Predescu wrote:
>
> Hi,
>
> I was wondering if there is any way in a __del__ method to know when it's
> invoked on the way out, as a result of the program going away?

It's a hack, but you can check sys.path: if it's None, then your program
is about to exit. To see why, check the output of 'python -vv -c "None"'.

Would probably be a good idea to add some flag to the sys module to be
able to check the current running state of the interpreter:

E.g. sys.state:
'startup' - interpreter is intializing
'ready' - interpreter is up and running
'exiting' - interpreter is exiting

> I have a __del__ method of a class that sends a message to a global variable.
> It happens that on the way out, that value in that variable is destroyed before
> the __del__ methods of my instances are invoked. The result is that I have a
> bogus value that doesn't respond to the usual methods anymore. How can I
> prevent sending messages to that object?
>
> A possible solution would be to use atexit() but this doesn't work if the user
> program that's using my library replaces it with its own function.

You can use sys.exitfunc() for Python programs.

Hope that helps.
--
Marc-Andre Lemburg
______________________________________________________________________
Y2000: 155 days left
Business: http://www.lemburg.com/
Python Pages: http://www.lemburg.com/python/
any way to know when the program is exiting? [ In reply to ]
Ovidiu Predescu wrote:
>
> I was wondering if there is any way in a __del__ method to know when
> it's invoked on the way out, as a result of the program going away?
>
> I have a __del__ method of a class that sends a message to a global
> variable. It happens that on the way out, that value in that
> variable is destroyed before the __del__ methods of my instances are
> invoked. The result is that I have a bogus value that doesn't
> respond to the usual methods anymore. How can I prevent sending
> messages to that object?

You rely on just what you described. Globals are nuked first, but
they don't end up with random bogus values, they are set to the one
and only None object.

def __del__(self):
if globalvar is None:
# we're on the way out...

- Gordon
any way to know when the program is exiting? [ In reply to ]
On Thu, 29 Jul 1999 13:45:01 +0200, "M.-A. Lemburg" <mal@lemburg.com> wrote:

> Ovidiu Predescu wrote:
> >
> > Hi,
> >
> > I was wondering if there is any way in a __del__ method to know when it's
> > invoked on the way out, as a result of the program going away?
>
> It's a hack, but you can check sys.path: if it's None, then your program
> is about to exit. To see why, check the output of 'python -vv -c "None"'.

Thanks, this seems to work. I looked on the source code and it seems that the
sys
module is treated specially in the cleanup phase.

Checking to see if my global variable is None doesn't work though. I guess this
happens because I use some weak references to avoid cyclic references and my
WeakReference C extension type gets collected before the classes that use it.
The global variable I'm trying to access from the __del__ method gets replaced
by a string object somehow, resulting in an exception being thrown (and ignored
by the interpreter).

> Would probably be a good idea to add some flag to the sys module to be
> able to check the current running state of the interpreter:
>
> E.g. sys.state:
> 'startup' - interpreter is intializing
> 'ready' - interpreter is up and running
> 'exiting' - interpreter is exiting

I agree, this would be nice.

Thanks a lot for all the responses!

Ovidiu

--
Ovidiu Predescu <ovidiu@cup.hp.com>
http://andromeda.cup.hp.com/ (inside HP's firewall only)
http://www.geocities.com/SiliconValley/Monitor/7464/
any way to know when the program is exiting? [ In reply to ]
It sounds like your class here relies on the existance of some other object
to help it clean up. Presumably this same object is required to help in
your class's __init__ method, and presumably it is not OK to just skip the
cleanup on the way out for some reason. In a case like this, I think it
would be safe to store a reference to that "global" as part of your
classes's __init__, as long as the "global" doesn't retain a reference to
your class instances. Then you can guarantee that the "global's" reference
count won't hit zero until all the objects that need it have been deleted,
even if it is no longer a "global" by that time, so your class can send
messages to the "global" through the reference that it owns.