faulthandler
--- 转储 Python 回溯信息¶
Added in version 3.3.
本模块包含当发生故障、超时或收到用户信号时可转储 Python 回溯信息的函数。 调用 faulthandler.enable()
可安装针对 SIGSEGV
, SIGFPE
, SIGABRT
, SIGBUS
和 SIGILL
信号的故障处理器。 你还可以在启动时通过设置 PYTHONFAULTHANDLER
环境变量或使用 -X
faulthandler
命令行选项来启用它们。
故障处理器可兼容系统故障处理器如 Apport 或 Windows 故障处理器。 本模块会在 sigaltstack()
函数可用时为信号处理器使用备用栈。 这允许它即使在栈溢出的情况下也能转储回溯信息。
故障处理程序将在灾难性场合调用,因此只能使用信号安全的函数(比如不能在堆上分配内存)。由于这一限制,与正常的 Python 跟踪相比,转储量是最小的。
只支持 ASCII 码。编码时会用到
backslashreplace
错误处理程序。每个字符串限制在 500 个字符以内。
只会显式文件名、函数名和行号。(不显示源代码)
上限是 100 页内存帧和 100 个线程。
反序排列:最近的调用最先显示。
默认情况下,Python 的跟踪信息会写入 sys.stderr
。为了能看到跟踪信息,应用程序必须运行于终端中。日志文件也可以传给 faulthandler.enable()
。
本模块是用 C 语言实现的,所以才能在崩溃或 Python 死锁时转储跟踪信息。
在 Python 启动时, Python 开发模式 会调用 faulthandler.enable()
。
转储跟踪信息¶
- faulthandler.dump_traceback(file=sys.stderr, all_threads=True)¶
将所有线程的跟踪数据转储到 file 中。如果 all_threads 为
False
,则只转储当前线程。参见
traceback.print_tb()
,可被用于打印回溯对象。在 3.5 版本发生变更: 增加了向本函数传入文件描述符的支持。
对 C 栈进行转储¶
Added in version 3.14.
- faulthandler.dump_c_stack(file=sys.stderr)¶
将当前线程的 C 栈追踪转储到 file 中。
如果 Python 构建版不支持或者操作系统没有提供栈追踪,那么此函数将打印一条错误消息而不是已转储的 C 栈。
C 栈兼容性Stack Compatibility¶
如果系统不支持 C 层级的 backtrace(3) 或 dladdr1(3),则 C 栈转储将不会执行。 将打印一条错误消息而不是打印栈。stack dumps will not work. An error will be printed instead of the stack.
此外,某些编译器不支持 CPython 的 C 栈转储实现。 因此,可能会打印不同的错误消息而不是打印栈,即使操作系统支持转储栈。
备注
转储 C 栈可能会相当慢,具体取决于调用栈中的二进制数据的 DWARF 级别。
故障处理程序的状态¶
- faulthandler.enable(file=sys.stderr, all_threads=True, c_stack=True)¶
启用默认的处理器:为
SIGSEGV
,SIGFPE
,SIGABRT
,SIGBUS
和SIGILL
信号安装处理器来转储 Python 回溯信息。 如果 all_threads 为True
,则会为每个运行中的线程产生回溯信息。 在其他情况下,将只转储当前线程。file 必须保持打开状态,直至停用故障处理程序为止:参见 文件描述符相关话题。
如果 c_stack 为
True
,则 C 栈追踪将在 Python 回溯之后打印,除非系统不支持它。 请参阅dump_c_stack()
了解有关兼容性的更多信息。在 3.5 版本发生变更: 增加了向本函数传入文件描述符的支持。
在 3.6 版本发生变更: 在 Windows 系统中,同时会安装一个 Windows 异常处理程序。
在 3.10 版本发生变更: 现在如果 all_threads 为 True,则转储信息会包含垃圾收集器是否正在运行。
在 3.14 版本发生变更: 如果禁用了 GIL 以防止数据竞争风险则只有当前线程会被转储。
在 3.14 版本发生变更: 现在如果 c_stack 为真值则转储将只显示 C 栈追踪。
- faulthandler.is_enabled()¶
检查故障处理程序是否被启用。
一定时间后转储跟踪数据。¶
- faulthandler.dump_traceback_later(timeout, repeat=False, file=sys.stderr, exit=False)¶
在 timeout 秒超时后,转储所有线程的回溯信息,或者如果 repeat 为
True
则每隔 timeout 秒执行一次转储。 如果 exit 为True
,则在转储回溯信息后调用_exit()
并设置 status=1。 (请注意_exit()
会立即关闭进程,这意味着不会做任何清理工作,如刷新文件缓冲区等。) 如果函数被调用两次,则新的调用将替代之前的形参并重置超时。 计时器的精度为亚秒级。file 必须保持打开状态,直至跟踪信息转储完毕,或调用了
cancel_dump_traceback_later()
:参见 文件描述符相关话题。本函数用一个看门狗线程实现。
在 3.5 版本发生变更: 增加了向本函数传入文件描述符的支持。
在 3.7 版本发生变更: 该函数现在总是可用。
- faulthandler.cancel_dump_traceback_later()¶
取消
dump_traceback_later()
的最后一次调用。
转储用户信号的跟踪信息。¶
- faulthandler.register(signum, file=sys.stderr, all_threads=True, chain=False)¶
注册一个用户信号:为 signum 信号安装一个处理程序,将所有线程或当前线程(all_threads 为
False
时)的跟踪信息转储到 file 中。如果 chain 为True
,则调用上一层处理程序。file 必须保持打开状态,直至该信号被
unregister()
注销:参见 文件描述符相关话题。Windows 中不可用。
在 3.5 版本发生变更: 增加了向本函数传入文件描述符的支持。
- faulthandler.unregister(signum)¶
注销一个用户信号:卸载由
register()
安装的 signum 信号处理程序。如果信号已注册,返回True
,否则返回False
。Windows 中不可用。
文件描述符相关话题¶
enable()
、 dump_traceback_later()
和 register()
保留其 file 参数给出的文件描述符。 如果文件关闭,文件描述符将被一个新文件重新使用;或者用 os.dup2()
替换了文件描述符,则跟踪信息将被写入另一个文件。 每次文件被替换时,都会再次调用这些函数。
示例¶
在 Linux 中启用和停用内存段故障的默认处理程序:
$ python -c "import ctypes; ctypes.string_at(0)"
Segmentation fault
$ python -q -X faulthandler
>>> import ctypes
>>> ctypes.string_at(0)
Fatal Python error: Segmentation fault
Current thread 0x00007fb899f39700 (most recent call first):
File "/opt/python/Lib/ctypes/__init__.py", line 486 in string_at
File "<stdin>", line 1 in <module>
Current thread's C stack trace (most recent call first):
Binary file "/opt/python/python", at _Py_DumpStack+0x42 [0x5b27f7d7147e]
Binary file "/opt/python/python", at +0x32dcbd [0x5b27f7d85cbd]
Binary file "/opt/python/python", at +0x32df8a [0x5b27f7d85f8a]
Binary file "/usr/lib/libc.so.6", at +0x3def0 [0x77b73226bef0]
Binary file "/usr/lib/libc.so.6", at +0x17ef9c [0x77b7323acf9c]
Binary file "/opt/python/build/lib.linux-x86_64-3.14/_ctypes.cpython-314d-x86_64-linux-gnu.so", at +0xcdf6 [0x77b7315dddf6]
Binary file "/usr/lib/libffi.so.8", at +0x7976 [0x77b73158f976]
Binary file "/usr/lib/libffi.so.8", at +0x413c [0x77b73158c13c]
Binary file "/usr/lib/libffi.so.8", at ffi_call+0x12e [0x77b73158ef0e]
Binary file "/opt/python/build/lib.linux-x86_64-3.14/_ctypes.cpython-314d-x86_64-linux-gnu.so", at +0x15a33 [0x77b7315e6a33]
Binary file "/opt/python/build/lib.linux-x86_64-3.14/_ctypes.cpython-314d-x86_64-linux-gnu.so", at +0x164fa [0x77b7315e74fa]
Binary file "/opt/python/build/lib.linux-x86_64-3.14/_ctypes.cpython-314d-x86_64-linux-gnu.so", at +0xc624 [0x77b7315dd624]
Binary file "/opt/python/python", at _PyObject_MakeTpCall+0xce [0x5b27f7b73883]
Binary file "/opt/python/python", at +0x11bab6 [0x5b27f7b73ab6]
Binary file "/opt/python/python", at PyObject_Vectorcall+0x23 [0x5b27f7b73b04]
Binary file "/opt/python/python", at _PyEval_EvalFrameDefault+0x490c [0x5b27f7cbb302]
Binary file "/opt/python/python", at +0x2818e6 [0x5b27f7cd98e6]
Binary file "/opt/python/python", at +0x281aab [0x5b27f7cd9aab]
Binary file "/opt/python/python", at PyEval_EvalCode+0xc5 [0x5b27f7cd9ba3]
Binary file "/opt/python/python", at +0x255957 [0x5b27f7cad957]
Binary file "/opt/python/python", at +0x255ab4 [0x5b27f7cadab4]
Binary file "/opt/python/python", at _PyEval_EvalFrameDefault+0x6c3e [0x5b27f7cbd634]
Binary file "/opt/python/python", at +0x2818e6 [0x5b27f7cd98e6]
Binary file "/opt/python/python", at +0x281aab [0x5b27f7cd9aab]
Binary file "/opt/python/python", at +0x11b6e1 [0x5b27f7b736e1]
Binary file "/opt/python/python", at +0x11d348 [0x5b27f7b75348]
Binary file "/opt/python/python", at +0x11d626 [0x5b27f7b75626]
Binary file "/opt/python/python", at PyObject_Call+0x20 [0x5b27f7b7565e]
Binary file "/opt/python/python", at +0x32a67a [0x5b27f7d8267a]
Binary file "/opt/python/python", at +0x32a7f8 [0x5b27f7d827f8]
Binary file "/opt/python/python", at +0x32ac1b [0x5b27f7d82c1b]
Binary file "/opt/python/python", at Py_RunMain+0x31 [0x5b27f7d82ebe]
<truncated rest of calls>
Segmentation fault