2014-05-05 40 views
0

atexit對處理程序我有一塊如下Python代碼:信號處理程序的調用和在Python

import sys 
import signal 
import atexit 

def release(): 
    print "Release resources..." 

def sigHandler(signo, frame): 
    release() 
    sys.exit(0) 

if __name__ == "__main__": 
    signal.signal(signal.SIGTERM, sigHandler) 
    atexit.register(release) 

    while True: 
     pass 

真正的代碼比這個片段複雜得多,但結構是相同的:即主函數保持無限循環。

我需要一個信號回調來釋放佔用的資源,比如DB句柄。 然後我添加一個SIGTERM處理程序,以防止服務器被終止,它只是簡單地調用釋放函數然後退出進程。 atexit其中一個旨在成功處理過程完成。

現在我遇到了一個問題,我只希望release只能在進程死亡時調用一次。我的代碼有什麼改進?

+0

我想問一下,如果真的有必要退出這種方式沒有正常關閉'main'循環? – user3159253

+0

一個廣泛使用的習慣用法是檢查我們是否應該打破循環,然後明確釋放資源。 – user3159253

+0

@ user3159253嗨,謝謝你的快速回復。我想是的,主循環實際上是一個http服務器模塊,我無法自行中斷環路。只有Ctrl-C可以停止它。是的,它的名字是瓶子T_T。 –

回答

4

那麼,根據documentation如果程序被非Python處理的信號所殺死,或者出現內部錯誤,或者調用了os._exit(),則不執行atexit處理程序。所以我會用這樣的事情(幾乎複製了你的代碼):

import sys 
import signal 
import atexit 

def release(): 
    print "Release resources..." 

def sigHandler(signo, frame): 
    sys.exit(0) 

if __name__ == "__main__": 
    atexit.register(release) 
    signal.signal(signal.SIGTERM, sigHandler) 

    while True: 
     pass 

我檢查release()在兩個TERM(發行在外)和INTR信號(Ctrl-C從鍵盤)的情況下調用一次,只有一次。如果你需要,你可以安裝更多的信號處理程序(例如HUP等)。如果你需要「更優雅的關機」,你應該找到一種方法來優雅地打破循環和/或安裝外部「關機處理程序」(在SIGKILL的情況下,你將不會得到乾淨釋放資源的機會),或者簡單地讓你的應用程序是ACID