2009-11-04 30 views
4

我有一個需要很長時間才能完成的程序。我想要 它能夠捕捉到SIGINT(ctrl-c)並且調用self.save_work()方法。SIGINT後保存工作

既然這樣,我signal_hander()不會因爲 self不是由程序到達signal_handler()時間定義的工作。

我該如何設置它,以便self.save_workSIGINT之後被調用?

#!/usr/bin/env python 
import signal 

def signal_handler(signal, frame):  
    self.save_work() # Does not work 
    exit(1) 
signal.signal(signal.SIGINT, signal_handler) 

class Main(object): 
    def do_stuff(self): 
     ... 
    def save_work(self): 
     ... 
    def __init__(self): 
     self.do_stuff() 
     self.save_work() 

if __name__=='__main__': 
    Main() 
+1

其一,你不能在一個函數中使用「self」。 – jldupont 2009-11-04 14:58:02

回答

4

如果你只是想趕上CTR + C,然後你可以趕上KeyboardInterrupt例外:

class Main(object): 
    def do_stuff(self): 
     ... 
    def save_work(self): 
     ... 
    def __init__(self): 
     try: 
      self.do_stuff() 
     except KeyboardInterrupt: 
      pass # Or print helpful info 
     self.save_work() 

不,我想這畢竟是一個不錯的設計。它看起來像你需要使用一個函數,而不是一個構造函數。

+0

...假設KeyboardInterrupt被拋出。我曾經有過這種情況。然而,sigint可以被處理。就我所能記得的那樣,必須處理線程和阻塞操作。除非我在其他地方使用我的代碼;) – exhuma 2009-11-04 15:09:21

+0

@exhuma,OP案例看起來很簡單。是的,我認爲我以前遇到過這種行爲與線程。 – 2009-11-04 15:13:31

+0

謝謝。 KeyboardInterrupt是我正在尋找的。 有時候我只用一個類來簡化參數的傳遞,而不使用全局變量。這被認爲是不好的設計? – unutbu 2009-11-04 15:28:35

2
import signal 

def signal_handler(signal, frame):  
    #do some stuff 

def main(): 
    #do some more stuff 


if __name__=='__main__': 
    signal.signal(signal.SIGINT, signal_handler) 
    main() 
+0

你需要'import signal'第一個 – 2012-08-30 22:56:12

3

通常,「工作」涉及某種大循環。馴服你的循環,並防止它在一個未知的一步打破,你可以使用下面的上下文管理器:

import signal 

class GracefulInterruptHandler(object): 

    def __init__(self, sig=signal.SIGINT): 
     self.sig = sig 

    def __enter__(self): 

     self.interrupted = False 
     self.released = False 

     self.original_handler = signal.getsignal(self.sig) 

     def handler(signum, frame): 
      self.release() 
      self.interrupted = True 

     signal.signal(self.sig, handler) 

     return self 

    def __exit__(self, type, value, tb): 
     self.release() 

    def release(self): 

     if self.released: 
      return False 

     signal.signal(self.sig, self.original_handler) 

     self.released = True 

     return True 

要使用:

import time 

/// do stuff: 
with GracefulInterruptHandler() as h: 
    for i in xrange(1000): 
     print "..." 
     time.sleep(1) 
     if h.interrupted: 
      print "interrupted!" 
      time.sleep(5) 
      break 

save_work() 

從這裏:https://gist.github.com/2907502