Reputation: 2831
I had some Python code that needed to be able to handle SIGINT. For this purpose I used something like this:
def mymethod(*params):
obj = MyObj(params)
try:
obj.do_some_long_stuff()
except KeyboardInterrupt:
obj.cleanup()
Awesome and really straightforward. Yay, Python is great!
However, I now need to also handle other signals, namely SIGTSTP and SIGQUIT. What I'm trying to do is something similar. Here's some pseudocode demonstrating what I'm trying to do with SIGTSTP (I hope it's clear enough):
def mymethod(*params):
obj = MyObj(params)
try:
obj.do_some_long_stuff()
catch SIGINT:
obj.cleanup()
catch SIGTSTP:
log_stop(obj) # Log that we stopped obj (add info about stop signal happening in obj-specific log file )
raise SIGTSTP # Do normal SIGTSTP behavior as if we didn't catch the signal
It seems that the way to go here is to use the signal module. However, my problem is that I can then can't access the object state anymore as I could with the KeyboardInterruptException
:
import os
import signal
def handler(signum, frame):
print "I can't access obj from here anymore!" # How to access obj from here?
signal.signal(signum, signal.SIG_DFL)
os.kill(os.getpid(), signum) # Rethrow signal, this time without catching it
def mymethod(*params):
obj = MyObj(params)
signal.signal(signal.SIGTSTP, handler)
obj.do_some_long_stuff()
So how can I solve this, i.e. handle the signal while still having some access to the object I'm working with?
Upvotes: 3
Views: 3578
Reputation: 100906
Or use a closure:
import os
import signal
def create_handler(obj):
def _handler(signum, frame):
print "obj is availiable here!"
print obj
signal.signal(signum, signal.SIG_DFL)
os.kill(os.getpid(), signum) # Rethrow signal, this time without catching it
return _handler
def mymethod(*params):
obj = MyObj(params)
signal.signal(signal.SIGTSTP, create_handler(obj))
obj.do_some_long_stuff()
create_handler(obj)
returns a handler function with access to obj
.
Upvotes: 10
Reputation: 5480
That would work under the condition that handler is a class-method and contains the self-member.
You could make obj global, since than you can access it from each function.
import os
import signal
obj = None
def handler(signum, frame):
log_stop(obj)
signal.signal(signum, signal.SIG_DFL)
os.kill(os.getpid(), signum) # Rethrow signal, this time without catching it
def mymethod(*params):
global obj # to signal that the obj we are changing here is the global obj
obj = MyObj(params)
handler.obj = obj
signal.signal(signal.SIGTSTP, handler)
obj.do_some_long_stuff()
(Note: Personally I avoid global parameters as much as possible, since global means really global).
Upvotes: 1