Python使用atexit模塊實現(xiàn)Golang的defer功能
在 Go 里面可以通過 defer 語句讓函數(shù)在結束時執(zhí)行預定義好的一些操作,舉個例子。
package main import "fmt" func main() { defer fmt.Println("高老師總能分享出好東西") fmt.Println("執(zhí)行結束") /* 執(zhí)行結束 高老師總能分享出好東西 */ }
這個功能非常方便,比如打開文件之后可以執(zhí)行 defer fp.Close(),這樣函數(shù)結束時會自動關閉文件句柄。那么在 Python 里面可不可以實現(xiàn)類似的功能呢?本次來聊一聊 atexit 模塊,它能幫我們實現(xiàn)類似的效果。
import atexit def exit_func(words): print(words) # 將函數(shù)注冊進去 atexit.register(exit_func, "高老師總能分享出好東西") print("Hello") print("World") """ Hello World 高老師總能分享出好東西 """
通過 atexit.register 將函數(shù)注冊進去之后,會在程序結束之前執(zhí)行,當然也可以同時注冊多個。
import atexit def exit_func(words): print(words) # 將函數(shù)注冊進去 atexit.register(exit_func, "高老師總能分享出好東西") atexit.register(exit_func, "S 老師今年 18,單身帶倆娃") atexit.register(exit_func, "只因^(* ̄(oo) ̄)^只因大(出海版)") print("Hello") print("World") """ Hello World 只因^(* ̄(oo) ̄)^只因大(出海版) S 老師今年 18,單身帶倆娃 高老師總能分享出好東西 """
如果同時注冊了多個函數(shù),那么會按照先入后出的順序執(zhí)行。非常簡單,其實 atexit 模塊就是將我們注冊的函數(shù)保存在了一個數(shù)組中,程序結束的時候,從后往前依次執(zhí)行。
既然可以注冊函數(shù),那么也可以取消注冊。
import atexit def exit_func1(words): print(words) def exit_func2(words): print(words) atexit.register(exit_func1, "高老師總能分享出好東西") atexit.register(exit_func1, "S 老師今年 18,單身帶倆娃") atexit.register(exit_func2, "只因^(* ̄(oo) ̄)^只因大(出海版)") # 取消注冊,所有注冊的 exit_func1 函數(shù)都會被刪除 atexit.unregister(exit_func1) """ 只因^(* ̄(oo) ̄)^只因大(出海版) """
而它的邏輯也很簡單,就是遍歷數(shù)組,如果和指定的函數(shù)相等,那么就刪掉。我們看一下源代碼。
如果你想將注冊的函數(shù)全部取消掉,那么也可以調用 _clear() 函數(shù)。
import atexit def exit_func1(words): print(words) def exit_func2(words): print(words) atexit.register(exit_func1, "高老師總能分享出好東西") atexit.register(exit_func1, "S 老師今年 18,單身帶倆娃") atexit.register(exit_func2, "只因^(* ̄(oo) ̄)^只因大(出海版)") atexit._clear()
此時程序不會有任何輸出,因為注冊的函數(shù)全部被清空了,同樣可以看一下它的源代碼。
最后就是函數(shù)的調用時機,我們注冊的函數(shù)在程序結束時才會調用,可不可以讓它們在任意時刻調用呢?
import atexit def exit_func1(words): print(words) def exit_func2(words): print(words) atexit.register(exit_func1, "AAA") atexit.register(exit_func1, "BBB") # 調用注冊的函數(shù),調用之后函數(shù)會被刪除 atexit._run_exitfuncs() print("++++++++++++++++") atexit.register(exit_func2, "CCC") atexit._run_exitfuncs() print("----------------") """ BBB AAA ++++++++++++++++ CCC ---------------- """
輸出結果表明,一旦調用了 _run_exitfuncs,所有注冊的函數(shù)會立即被調用。我們看一下源代碼。
以上就是 atexit 模塊的用法,那我們如何基于它實現(xiàn) Golang 的 defer 呢?
from typing import Callable import atexit def defer(func: Callable, *args, **kwargs): atexit.register(func, *args, **kwargs) def get_file_content(file_path): fp = open(file_path, encoding="utf-8") defer(fp.close) # 注冊函數(shù) content = fp.read() # do something ... atexit._run_exitfuncs() # 觸發(fā)注冊函數(shù)執(zhí)行 get_file_content("config.py")
不過這個例子明顯有點刻意了,因為必須要在函數(shù)的結尾調用 atexit._run_exitfuncs,而之所以要實現(xiàn) Go 的 defer,就是為了避免遺忘某些邏輯。
如果每次都要在函數(shù)結尾調用 atexit._run_exitfuncs,那還不如不用,于是我們可以考慮使用裝飾器。
from typing import Callable from functools import wraps import atexit def defer(func: Callable, *args, **kwargs): atexit.register(func, *args, **kwargs) # 給函數(shù)賦予 defer 功能 def enable_defer(func): @wraps(func) def inner(*args, **kwargs): ret = func(*args, **kwargs) atexit._run_exitfuncs() return ret return inner @enable_defer # 通過裝飾器,讓函數(shù)支持 defer 功能 def get_file_content(file_path): fp = open(file_path, encoding="utf-8") # 注冊函數(shù) defer(fp.close) defer(print, "get_file_content 函數(shù)實現(xiàn)了 defer 功能") content = fp.read() print("函數(shù)執(zhí)行結束") get_file_content("config.py") print("程序結束") """ 函數(shù)執(zhí)行結束 get_file_content 函數(shù)實現(xiàn)了 defer 功能 程序結束 """
輸出結果表明,在函數(shù)結束后,通過 defer 注冊的函數(shù)執(zhí)行了。
以上就是Python使用atexit模塊實現(xiàn)Golang的defer功能的詳細內容,更多關于Python atexit實現(xiàn)defer功能的資料請關注腳本之家其它相關文章!
相關文章
使用pytorch提取卷積神經(jīng)網(wǎng)絡的特征圖可視化
這篇文章主要給大家介紹了關于使用pytorch提取卷積神經(jīng)網(wǎng)絡的特征圖可視化的相關資料,文中給出了詳細的思路以及示例代碼,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2022-03-03Python+selenium 獲取瀏覽器窗口坐標、句柄的方法
今天小編就為大家分享一篇Python+selenium 獲取瀏覽器窗口坐標、句柄的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-10-10對pandas將dataframe中某列按照條件賦值的實例講解
今天小編就為大家分享一篇對pandas將dataframe中某列按照條件賦值的實例講解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-11-11Python實現(xiàn)將Excel轉換成xml的方法示例
這篇文章主要介紹了Python實現(xiàn)將Excel轉換成xml的方法,涉及Python針對Excel文件的讀取、遍歷、節(jié)點設置與xml生成等相關操作技巧,需要的朋友可以參考下2018-08-08如何配置關聯(lián)Python 解釋器 Anaconda的教程(圖解)
這篇文章主要介紹了如何配置關聯(lián)Python 解釋器 Anaconda的教程,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習火鍋工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-04-04