atexit
--- 退出處理器¶
atexit
模組定義了用於註冊和登出清理函式的函式。這樣註冊的函式會在直譯器正常終止時自動執行。atexit
會以與註冊時 相反 的順序執行這些函式;如果你註冊了 A
, B
和 C
,那麼在直譯器終止時,它們會以 C
, B
, A
的順序執行。
注意:當程式被一個 Python 未處理的訊號終止,或檢測到 Python 的致命內部錯誤,或呼叫 os._exit()
時,透過此模組註冊的函式不會被呼叫。
注意:在清理函式中註冊或登出函式的效果是未定義的。
在 3.7 版更改: 當與 C-API 子直譯器一起使用時,註冊的函式是侷限於其註冊時所在的直譯器的。
- atexit.register(func, *args, **kwargs)¶
註冊 func 為一個在程式終止時執行的函式。任何要傳遞給 func 的可選引數都必須作為引數傳遞給
register()
。可以多次註冊相同的函式和引數。在程式正常終止時(例如,如果呼叫了
sys.exit()
或主模組執行完畢),所有註冊的函式都將以後進先出的順序被呼叫。這裡的假設是,低層模組通常會比高層模組先匯入,因此必須稍後清理。如果在執行退出處理器期間引發了異常,則會列印回溯資訊(除非引發的是
SystemExit
)並儲存異常資訊。在所有退出處理器都有機會執行之後,最後一個被引發的異常會被重新引發。此函式會返回 func,這使得它可以被用作裝飾器。
警告
從已註冊的函式中啟動新執行緒或呼叫
os.fork()
可能導致主 Python 執行時執行緒釋放執行緒狀態,而內部threading
例程或新程序試圖使用該狀態之間的競爭條件。這可能導致崩潰而不是乾淨的關閉。在 3.12 版更改: 在已註冊的函式中嘗試啟動新執行緒或
os.fork()
一個新程序現在會導致RuntimeError
。
- atexit.unregister(func)¶
從直譯器關閉時要執行的函式列表中移除 func。如果 func 之前沒有被註冊,
unregister()
會靜默地不做任何事。如果 func 被註冊了多次,那麼該函式在atexit
呼叫棧中的每一次出現都將被移除。在登出期間,內部會使用相等性比較(==
),因此函式引用不需要具有相同的標識。
atexit
示例¶
以下簡單示例演示了一個模組如何在匯入時從檔案中初始化一個計數器,並在程式終止時自動儲存計數器的更新值,而無需依賴應用程式在終止時對此模組進行顯式呼叫。
try:
with open('counterfile') as infile:
_count = int(infile.read())
except FileNotFoundError:
_count = 0
def incrcounter(n):
global _count
_count = _count + n
def savecounter():
with open('counterfile', 'w') as outfile:
outfile.write('%d' % _count)
import atexit
atexit.register(savecounter)
位置引數和關鍵字引數也可以傳遞給 register()
,以便在呼叫註冊的函式時傳遞給它。
def goodbye(name, adjective):
print('Goodbye %s, it was %s to meet you.' % (name, adjective))
import atexit
atexit.register(goodbye, 'Donny', 'nice')
# or:
atexit.register(goodbye, adjective='nice', name='Donny')
用作裝飾器
import atexit
@atexit.register
def goodbye():
print('You are now leaving the Python sector.')
這隻適用於可以無引數呼叫的函式。