在Python中,我可以使用atexit模块来注册Python退出时要执行的函数。有没有办法检索已注册的退出处理程序列表?
答案 0 :(得分:5)
在Python 2中,模块仍然只能作为Python使用,atexit
模块有一个半私有列表:
atexit._exithandlers
包含所有已注册的退出处理程序。
在Python 3中,该模块已经在C中重新编码,并且该列表不再可访问,因此对于Python 3而言,恐怕是运气不好。
您必须将Python 2 pure-python version移植到Python 3,并确保使用它而不是C版本来重新访问列表。
答案 1 :(得分:4)
这是访问已注册函数(可调用对象)的纯Python方法,但不是用于调用它们的参数的方法。有点麻烦,但是对于调试之类的事情,它就可以了:
Python 3.5.3 (default, Jul 9 2020, 13:00:10)
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import atexit
>>> class Capture:
... def __init__(self):
... self.captured = []
... def __eq__(self, other):
... self.captured.append(other)
... return False
...
>>> c = Capture()
>>> atexit.unregister(c)
>>> print(c.captured)
[<function <lambda> at 0x7fc47631d730>, <built-in function write_history_file>]
>>> atexit.unregister(c.captured[0]) # this will work
它是如何工作的:如记录所示,atexit.unregister(c)
从回调列表中删除了c
的所有出现。通过依次将每个回调与c
进行相等性比较来实现。这将导致呼叫c.__eq__(other)
,其中other
是回调(永远不会跳过此呼叫,反之则引发NotImplemented
)。 Capture.__eq__
然后复制其参数。
答案 2 :(得分:2)
这是@BCarvello以功能形式提供的解决方案:
import atexit
def get_atexit_functions():
funs = []
class Capture:
def __eq__(self, other):
funs.append(other)
return False
c = Capture()
atexit.unregister(c)
return funs
答案 3 :(得分:1)
在Python 3中,atexit._exithandlers列表不可用,但如果您只需要计算已注册的回调数,则可以这样做:
atexit._ncallbacks()
演示:
# python3
Python 3.5.3rc1 (default, Jan 3 2017, 04:40:57)
[GCC 6.3.0 20161229] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import atexit
>>> atexit._ncallbacks()
2
答案 4 :(得分:0)
有一个公开功能要求公开此信息(bpo-32082)。该请求引用了Cython模块here形式的解决方法,其关键部分是:
from cpython.ref cimport PyObject
# Internal structures defined in the CPython source in
# Modules/atexitmodule.c and subject to (but unlikely to) change. Watch
# https://bugs.python.org/issue32082 for a request to (eventually)
# re-expose more of the atexit module's internals to Python
ctypedef struct atexit_callback:
PyObject* func
PyObject* args
PyObject* kwargs
ctypedef struct atexitmodule_state:
atexit_callback** atexit_callbacks
int ncallbacks
int callback_len
cdef extern from "Python.h":
void* PyModule_GetState(object module)
def _get_exithandlers():
"""Return list of exit handlers registered with the atexit module."""
cdef atexitmodule_state* state
cdef atexit_callback callback
cdef list exithandlers
cdef int idx
cdef object kwargs
state = <atexitmodule_state*>PyModule_GetState(atexit)
if not state:
raise RuntimeError("atexit module state missing or corrupt")
exithandlers = []
for idx in range(state.ncallbacks):
callback = state.atexit_callbacks[idx][0]
if callback.kwargs:
kwargs = <object>callback.kwargs
else:
kwargs = {}
exithandlers.append((<object>callback.func,
<object>callback.args,
kwargs))
return exithandlers