我有一些需要能够处理SIGINT的Python代码。为此,我使用了这样的东西:
def mymethod(*params):
obj = MyObj(params)
try:
obj.do_some_long_stuff()
except KeyboardInterrupt:
obj.cleanup()
太棒了,真的很直白。是的,Python很棒!
但是,我现在还需要处理其他信号,即SIGTSTP和SIGQUIT。我正在尝试做的是类似的事情。这里有一些伪代码演示了我正在尝试用SIGTSTP做什么(我希望它足够清楚):
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
这里的方法似乎是使用信号模块。但是,我的问题是我无法再使用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()
那么如何解决这个问题,即在仍然可以访问我正在使用的对象时处理信号呢?
答案 0 :(得分:9)
或使用闭包:
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)
返回一个可以访问obj
的处理函数。
答案 1 :(得分:1)
这可以在handler是一个类方法并且包含self-member的条件下工作。
你可以使obj成为全局,因为你可以从每个函数访问它。
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()
(注意:我个人尽可能避免使用全局参数,因为全局意味着真正的全局参数。)