atexit --- 退出處理函式


Theatexit module defines functions to register and unregister cleanupfunctions. Functions thus registered are automatically executed upon normalinterpreter termination.atexit runs these functions in thereverseorder in which they were registered; if you registerA,B, andC,at interpreter termination time they will be run in the orderC,B,A.

注意:當程式被一個不是來自 Python 的訊號終止、偵測到有 Python 嚴重內部錯誤時或者os._exit() 被呼叫時,透過此模組註冊的函式就不會被呼叫。

注意:在清理函式中註冊或註銷函式的作用並未定義。

在 3.7 版的變更:當與 C-API 子直譯器 (subinterpreter) 一起使用時,已註冊函式對於它們所註冊的直譯器來說是區域的 (local)。

atexit.register(func,*args,**kwargs)

func 註冊為要在終止時執行的函式。任何要傳遞給func 的可選引數都必須作為引數傳遞給register()。可以多次註冊相同的函式和引數。

在程式正常終止時(例如呼叫sys.exit() 或主要模組執行完成),所有已註冊函式都會依照後進先出的順序呼叫。這邊做的假設是較低階的模組通常會在較高階模組之前被引入,因此較低階模組必須在比較後面才被清理。

如果在執行退出處理函式期間引發例外,則會列印回溯 (traceback)(除非引發SystemExit)並儲存例外資訊。在所有退出處理函式都有嘗試運作過後,將重新引發最後一個引發的例外。

該函式回傳func,這使得可以將其作為裝飾器使用。

警告

啟動新執行緒或從已註冊函式呼叫os.fork() 可能會導致 Python 主要 runtime 執行緒釋放執行緒狀態,而內部threading 例程或新行程嘗試使用該狀態所形成的競態條件 (race condition)。這可能會導致崩潰 (crash) 而不是完整關閉中止。

在 3.12 版的變更:嘗試在已註冊函式中啟動新執行緒或os.fork() 新行程現在會導致RuntimeError

atexit.unregister(func)

Removefunc from the list of functions to be run at interpreter shutdown.unregister() silently does nothing iffunc was not previouslyregistered. Iffunc has been registered more than once, every occurrenceof that function in theatexit call stack will be removed. Equalitycomparisons (==) are used internally during unregistration, so functionreferences do not need to have matching identities.

也參考

readline 模組

Useful example ofatexit to read and writereadline historyfiles.

atexit Example

以下的簡單範例示範了模組如何在被引入時以檔案來初始化計數器,並在程式終止時自動儲存計數器的更新值,而不需要仰賴應用程式在終止時明確呼叫該模組。

try:withopen('counterfile')asinfile:_count=int(infile.read())exceptFileNotFoundError:_count=0defincrcounter(n):global_count_count=_count+ndefsavecounter():withopen('counterfile','w')asoutfile:outfile.write('%d'%_count)importatexitatexit.register(savecounter)

位置引數和關鍵字引數也可以被傳遞給register(),以便在呼叫時也傳遞給已註冊函式:

defgoodbye(name,adjective):print('Goodbye%s, it was%s to meet you.'%(name,adjective))importatexitatexit.register(goodbye,'Donny','nice')# 或是:atexit.register(goodbye,adjective='nice',name='Donny')

作為裝飾器使用:

importatexit@atexit.registerdefgoodbye():print('You are now leaving the Python sector.')

這只適用於可以不帶引數呼叫的函式。