3

SIGINT を処理できるようにするために必要な Python コードがいくつかありました。この目的のために、私は次のようなものを使用しました:

def mymethod(*params):
  obj = MyObj(params)
  try:
    obj.do_some_long_stuff()
  except KeyboardInterrupt:
    obj.cleanup()

素晴らしく、本当に簡単です。やあ、パイソンはいいぞ!

ただし、他のシグナル、つまり 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 に答える