Python 标准库 atexit 退出处理

本内容来自:https://gairuo.com

说明

《Python 教程》 持续更新中,提供建议、纠错、催更等加作者微信: gr99123(备注:pandas教程)和关注公众号「盖若」ID: gairuo。跟作者学习,请进入 Python学习课程。欢迎关注作者出版的书籍:《深入浅出Pandas》 和 《Python之光》。

本内容来自:https://gairuo.com

Python 的 atexit 模块定义了清理函数的注册和反注册函数. 被注册的函数会在解释器正常终止时执行。atexit 会按照注册顺序的逆序执行; 如果你注册了 A, B 和 C, 那么在解释器终止时会依序执行 C, B, A。

方法

Python里atexit,和Unix系统是同一个机制。 在程序的任何地方都可以注册一个或多个回调函数,在程序退出时执行。

atexit 模块只有两个方法:

atexit.register():注册回调方法,解释器退出时执行

atexit.unregister():注销回调方法

atexit.register()

回调顺序为先进后出,应该是一个栈结构。语法为:

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

将 func 注册为终止时执行的函数. 任何传给 func 的可选的参数都应当作为参数传给 register(). 可以多次注册同样的函数及参数.

在正常的程序终止时 (举例来说, 当调用了 sys.exit() 或是主模块的执行完成时), 所有注册过的函数都会以后进先出的顺序执行. 这样做是假定更底层的模块通常会比高层模块更早引入, 因此需要更晚清理.

如果在 exit 处理句柄执行期间引发了异常,将会打印回溯信息 (除非引发的是 SystemExit) 并且异常信息会被保存。 在所有 exit 处理句柄都获得运行机会之后,所引发的最后一个异常会被重新引发。

这个函数返回 func 对象,可以把它当作装饰器使用。

支持装饰器:

import atexit

@atexit.register

def foo():

print('我走了。')

# 我走了。

atexit.unregister()

语法为:atexit.unregister(func)。

将 func 移出当解释器关闭时要运行的函数列表。 如果 func 之前未被注册则 unregister() 将静默地不做任何事。 如果 func 已被注册一次以上,则该函数每次在 atexit 调用栈中的出现都将被移除。 当取消注册时会在内部使用相等性比较 (==),因而函数引用不需要具有匹配的标识号。

其他方法

除了以上两个主要方法外,还有以下几个方法:

# 清除以前注册的退出功能列表

atexit._clear()

# 返回已注册的退出函数数

atexit._ncallbacks() # 1

# 运行所有注册的退出功能。

# 如果callaback引发异常,与 sys.unraisablehook 记录相同

atexit._run_exitfuncs()

# 我走了。

注意

通过该模块注册的函数, 在程序被未被 Python 捕获的信号杀死时并不会执行, 在检测到 Python 内部致命错误以及调用了 os._exit() 时也不会执行。

虽然无论是正常退出、还是异常退出(返回值非0),这个机制都会被触发; 但是,在被杀掉时——比如Ctrl+c,或kill -9等场景,是被外部信号(signal)控制退出——都是不会生效的。

此模块的方法不适用于交互式执行环境,如 jupyter 等。

场景

以下是使用场景:

在程序异常退出的时候(比如ctrl+c)保存一些内容到文件

统计程序运行情况,比如运行时长

退出程序时做一些清理,比如产生的缓存、垃圾文件

记录程序执行日志

等等

注意,场景是解释器正常终止。

示例

统计脚本执行时间

简单的写法,不侵入业务代码。

import time

import atexit

start = time.time()

atexit.register(lambda: print('用时(秒):', time.time()-start))

time.sleep(3)

print('hello!')

'''

hello!

用时(秒): 3.0034449100494385

'''

用文件记录执行脚本执行次数

在同目录下会生成一个 counterfile 文件,执行脚本三次,文件中的值为 3。

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)

# 每次执行加1

incrcounter(1)

import atexit

atexit.register(savecounter)

位置和关键字参数

要注意的是,同一个函数注册两次,会执行两次。

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')

'''

Goodbye Donny, it was nice to meet you.

Goodbye Donny, it was nice to meet you.

'''

装饰器

只有在函数不需要任何参数调用时才能工作。

import atexit

@atexit.register

def goodbye():

print('You are now leaving the Python sector.')

参考

https://docs.python.org/zh-cn/3/library/atexit.html

https://note.qidong.name/2018/08/python-atexit/

相关内容

Python 异步爬虫获取豆瓣TOP250电影

2022-12-27 09:14:55

< tkinter Tk 图形用户界面(GUI)

Python 内置标准库

copy 复制操作 >

更新时间:2022-05-01 10:44:37

标签:python

退出

细数韩国全州必去旅游景点
什么叫世锦赛什么叫锦标赛(世锦赛和锦标赛有什么区别)