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.')
这仅适用于可以不带参数调用的函数。