Python atexit 模組
Posted on Sep 21, 2019 in Python 程式設計 - 初階 by Amo Chen ‐ 2 min read
最近在看 Elastic APM agent for Python 的原始碼時,看到該專案的開發者有使用 atexit 模組,在 APM agent 關閉前先關閉 metrics collect timer 。
由於對 atexit
不甚熟悉,因此特以此文研究一番。
本文環境
- Python 3.6.5
Exit handlers
The atexit module defines functions to register and unregister cleanup functions.
atexit
模組可以讓我們註冊(register)或取消(unregister)程式結束時(更嚴格的說是 Python 直譯器 / interpreter 結束執行之前)要執行的函數,,這些函數通常是用來進行收尾的程式,所以被稱為 cleanup functions ,例如關閉連線、關閉檔案等等。
例如以下範例,會在程式結束時列印 Goodbye
:
import atexit
def main():
for x in range(10):
print(x)
@atexit.register
def print_goodbye():
print('Goodbye')
if __name__ == '__main__':
main()
以下為上述程式的執行結果,可以看到 main()
函式中沒有 print('Goodbye')
但是最後仍印出 Goodbye 的字串,這就是 atexit 模組的用途,讓程式在結束前執行指定的函式:
0
1
2
3
4
5
6
7
8
9
Goodbye
執行順序
atexit
也支援註冊多個函式:
import atexit
def A():
print('A')
def B():
print('B')
def C():
print('C')
if __name__ == '__main__':
atexit.register(A)
atexit.register(B)
atexit.register(C)
上述執行結果:
C
B
A
如果註冊多個函式時,函式的執行順序會是註冊順序的相反:
atexit runs these functions in the reverse order in which they were registered; if you register A, B, and C, at interpreter termination time they will be run in the order C, B, A.
atexit 注意事項
The functions registered via this module are not called when the program is killed by a signal not handled by Python, when a Python fatal internal error is detected, or when os._exit() is called.
官方文件記載, atexit
有 3 種情況會無法執行:
- 被程式沒處理到的 signal kill
- 發生 Python 內部嚴重的錯誤時,例如 Python 本身的 bug
- 呼叫
os._exit()
時
例如:
import atexit
import os
def A():
print('A')
if __name__ == '__main__':
atexit.register(A)
os._exit(1)
上述範例,不會執行 atexit 所註冊的函式,因為使用到 os._exit(1)
。
或者我們以指令 kill -9 <pid>
停止執行以下程式時,也不會執行 atexit
:
import atexit
from time import sleep
def A():
print('A')
if __name__ == '__main__':
atexit.register(A)
while True:
print(1)
sleep(10)
以上,就是 Python atexit 模組的簡單說明囉。
References
https://docs.python.org/3/library/atexit.html