结束前的倔强

结束前的倔强

结束前的倔强

有时候我们希望在程序执行一些函数,比如通知或者妥善处理一些善后工作,可以实现的方法很多,比如借助异常、with 或者合理的函数布局都可以。Python 提供了一种更加优雅的做法—— atexit 模块。

atexit 模块提供的接口非常简单:

  • atexit.register(func, *args, **kwargs) 注册回调函数
  • atexit.unregister(func) 撤销回调函数

非常简单,其中 func 参数是函数对象,kwargs 参数会作为回调函数执行时的参数。

简单的例子

import atexit
def on_exit(*args):
    print("I'm quiting.", args)
atexit.register(on_exit)
atexit.register(on_exit, "I will miss you!")
# this will unregister all on exit callbacks named 'on_exit'
#atexit.unregister(on_exit)
print("Start.")
print("End.")

上面代码的执行结果:

Start.
End.
I'm quiting. ('I will miss you!',)
I'm quiting. ()

可以看到在 “End” 之后,两个 callback 被执行了,但是逆序执行。

原理

在 atexit 的实现中,将所有注册函数对象连接在一起,退出前逆序依次执行所有回调函数。也可以认为回调函数链表总是在头部插入最新的记录。如果我们在注册了上面两个回调后,再注册一个 new_callback() ,callback 链表看起来会是这样。

撤销回调

atexit.unregister 会撤销函数对象的所有回调,对于前面的代码,会取消两个 on_exit 回调,再次上面的代码只会输出:

Start.
End.

装饰器注册

除了经典的 atexit.register 接口注册回调函数外,atexit.register 还可以用装饰器风格注册回调。

import atexit
@atexit.register