faulthandler --- 轉儲 Python 回溯

在 3.3 版本加入。


此模組包含的函式可以在發生故障、超時或收到使用者訊號時顯式地轉儲 Python 回溯資訊。呼叫 faulthandler.enable() 可為 SIGSEGVSIGFPESIGABRTSIGBUSSIGILL 訊號安裝故障處理程式。你也可以透過設定 PYTHONFAULTHANDLER 環境變數或使用 -X faulthandler 命令列選項在啟動時啟用它們。

故障處理程式與 Apport 或 Windows 故障處理程式等系統故障處理程式相容。如果 sigaltstack() 函式可用,該模組會為訊號處理程式使用備用堆疊。這使得它即使在堆疊溢位時也能轉儲回溯資訊。

故障處理程式是在發生災難性情況時呼叫的,因此只能使用訊號安全 (signal-safe) 的函式(例如,它不能在堆上分配記憶體)。由於此限制,與正常的 Python 回溯資訊相比,回溯資訊的轉儲是最小化的。

  • 只支援 ASCII。編碼時使用 backslashreplace 錯誤處理程式。

  • 每個字串限制為 500 個字元。

  • 只顯示檔名、函式名和行號。(沒有原始碼)

  • 它被限制在 100 個幀和 100 個執行緒內。

  • 順序是顛倒的:最新的呼叫會最先顯示。

預設情況下,Python 回溯資訊會寫入 sys.stderr。要看到回溯資訊,應用程式必須在終端中執行。或者也可以將日誌檔案傳遞給 faulthandler.enable()

該模組是用 C 實現的,因此可以在崩潰或 Python 死鎖時轉儲回溯資訊。

Python 開發模式 會在 Python 啟動時呼叫 faulthandler.enable()

參見

模組 pdb

適用於 Python 程式的互動式原始碼偵錯程式。

模組 traceback

提取、格式化和列印 Python 程式堆疊跟蹤的標準介面。

轉儲回溯資訊

faulthandler.dump_traceback(file=sys.stderr, all_threads=True)

將所有執行緒的回溯資訊轉儲到 file 中。如果 all_threadsFalse,則只轉儲當前執行緒。

參見

traceback.print_tb() 可用於列印回溯物件。

在 3.5 版更改: 增加了向此函式傳遞檔案描述符的支援。

轉儲 C 堆疊

在 3.14 版本加入。

faulthandler.dump_c_stack(file=sys.stderr)

將當前執行緒的 C 堆疊跟蹤轉儲到 file 中。

如果 Python 構建不支援或作業系統不提供堆疊跟蹤,那麼這會列印一個錯誤資訊,而不是轉儲 C 堆疊。

C 堆疊相容性

如果系統不支援 C 級別的 backtrace(3)dladdr1(3),那麼 C 堆疊轉儲將無法工作。將會列印錯誤資訊而不是堆疊。

此外,某些編譯器不支援 CPython 的 C 堆疊轉儲實現。因此,即使作業系統支援轉儲堆疊,也可能會列印一個不同的錯誤資訊而不是堆疊。

備註

轉儲 C 堆疊的速度可能會非常慢,具體取決於呼叫堆疊中二進位制檔案的 DWARF 級別。

故障處理程式狀態

faulthandler.enable(file=sys.stderr, all_threads=True, c_stack=True)

啟用故障處理程式:為 SIGSEGVSIGFPESIGABRTSIGBUSSIGILL 訊號安裝處理程式以轉儲 Python 回溯資訊。如果 all_threadsTrue,則為每個正在執行的執行緒生成回溯資訊。否則,只轉儲當前執行緒。

file 必須保持開啟狀態,直到故障處理程式被停用:請參閱檔案描述符問題

如果 c_stackTrue,那麼 C 堆疊跟蹤將在 Python 回溯之後列印,除非系統不支援。有關相容性的更多資訊,請參閱 dump_c_stack()

在 3.5 版更改: 增加了向此函式傳遞檔案描述符的支援。

在 3.6 版更改: 在 Windows 上,還會安裝一個 Windows 異常處理程式。

在 3.10 版更改: 如果 all_threads 為真,轉儲現在會提及垃圾回收器回收是否正在執行。

在 3.14 版更改: 如果停用了 GIL,為避免資料競爭的風險,只會轉儲當前執行緒。

在 3.14 版更改: 如果 c_stack 為真,轉儲現在會顯示 C 堆疊跟蹤。

faulthandler.disable()

停用故障處理程式:解除安裝由 enable() 安裝的訊號處理程式。

faulthandler.is_enabled()

檢查故障處理程式是否已啟用。

超時後轉儲回溯資訊

faulthandler.dump_traceback_later(timeout, repeat=False, file=sys.stderr, exit=False)

timeout 秒的超時後,轉儲所有執行緒的回溯資訊;如果 repeatTrue,則每隔 timeout 秒轉儲一次。如果 exitTrue,則在轉儲回溯資訊後以狀態碼 1 呼叫 _exit()。(注意 _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_threadsFalse,則為當前執行緒)轉儲到 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