2012-11-14 31 views
3

我有一些需要能夠處理SIGINT的Python代碼。爲此我使用的是這樣的:在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() 

那麼,如何解決這個問題,即處理同時還具有一些訪問對象的信號我正在與?

回答

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的處理函數。

+0

有趣,沒想到那個!這似乎是最優雅的解決方案。謝謝。 – jjst

+0

剛剛實施,是的:優雅和工作。 – bux

0

好吧,看來我剛剛遇到了rubber duck problem solving的情況,而且我在仔細製作我的問題時找到了答案。無論如何,我想我可能會完成發佈並回答它,以防萬一它可以幫助別人(另外,我不是100%確定我的解決方案,並且對信號沒有信心)。所以這裏有雲:

Python方法都只是標準的對象,這樣就意味着我基本上可以做這樣的事情:

import os 
import signal 

def handler(signum, frame): 
    log_stop(handler.obj) 
    signal.signal(signum, signal.SIG_DFL) 
    os.kill(os.getpid(), signum) # Rethrow signal, this time without catching it 

def mymethod(*params): 
    obj = MyObj(params) 
    handler.obj = obj 
    signal.signal(signal.SIGTSTP, handler) 
    obj.do_some_long_stuff() 
1

將在該處理程序是一個類的方法,包含的條件下工作自成員。

您可以使obj爲全局,因爲您可以從每個函數訪問它。 (注意:我個人儘量避免使用全局參數,因爲全局意味着真正全球化)。

+0

我的答案代碼中有一些語法混亂,我需要在處理函數中用'log_stop(handler.obj)'替換'log_stop(self.obj)',以使其表現符合預期。至於使用全局變量,我考慮過了,但似乎他們不必要的使用通常是不被接受的,所以我一直在尋找替代解決方案,並以全局變量作爲最後的手段。 – jjst