3

我有一些 Python 代码需要能够处理 SIGINT。为此,我使用了这样的东西:

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()   

那么我该如何解决这个问题,即在处理信号的同时仍然可以访问我正在使用的对象?

4

2 回答 2

10

或者使用闭包:

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

于 2012-11-14T11:48:45.983 回答
1

这将在处理程序是类方法并包含自身成员的条件下工作。

您可以将 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()

(注意:我个人尽可能避免使用全局参数,因为全局意味着真正的全局)。

于 2012-11-14T11:31:39.100 回答