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