traceback — 列印或檢索堆疊回溯

原始碼: Lib/traceback.py


此模組提供了一個標準介面,用於提取、格式化和列印 Python 程式的堆疊跟蹤。 它比直譯器的預設回溯顯示更靈活,因此可以配置輸出的某些方面。 最後,它包含一個實用程式,用於捕獲有關異常的足夠資訊,以便稍後列印它,而無需儲存對實際異常的引用。 由於異常可能是大型物件圖的根,因此此實用程式可以顯著改善記憶體管理。

該模組使用 回溯物件 — 這些是 types.TracebackType 型別的物件,它們被分配給 __traceback__ BaseException 例項的欄位。

另請參閱

模組 faulthandler

用於在故障、超時後或在使用者訊號上顯式轉儲 Python 回溯。

模組 pdb

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

該模組的 API 可以分為兩部分

  • 模組級函式提供基本功能,這對於互動式檢查異常和回溯非常有用。

  • TracebackException 類及其輔助類 StackSummaryFrameSummary。 這些在生成的輸出中提供了更大的靈活性,並且能夠儲存稍後格式化所需的資訊,而無需保留對實際異常和回溯物件的引用。

模組級函式

traceback.print_tb(tb, limit=None, file=None)

如果 limit 為正,則從 回溯物件 tb (從呼叫者的幀開始)列印最多 limit 個堆疊跟蹤條目。 否則,列印最後 abs(limit) 個條目。 如果省略 limit 或為 None,則列印所有條目。 如果省略 file 或為 None,則輸出轉到 sys.stderr;否則它應該是一個開啟的 檔案類檔案物件 來接收輸出。

注意

limit 引數的含義與 sys.tracebacklimit 的含義不同。 負 limit 值對應於 sys.tracebacklimit 的正值,而正 limit 值的行為無法透過 sys.tracebacklimit 實現。

在 3.5 版本中更改: 添加了負 limit 支援。

traceback.print_exception(exc, /, [value, tb, ]limit=None, file=None, chain=True)

將來自 回溯物件 tb 的異常資訊和堆疊跟蹤條目列印到 file。 這與 print_tb() 不同,具體如下

  • 如果 tb 不是 None,它會列印一個標頭 Traceback (most recent call last):

  • 它在堆疊跟蹤之後列印異常型別和 value

  • 如果 type(value)SyntaxError 並且 value 具有適當的格式,它會打印發生語法錯誤的行,並帶有一個插入符號,指示錯誤的大概位置。

從 Python 3.10 開始,可以傳遞異常物件作為第一個引數,而不是傳遞 valuetb。 如果提供了 valuetb,則會忽略第一個引數,以提供向後相容性。

可選的 limit 引數與 print_tb() 的含義相同。 如果 chain 為 true(預設),則還將列印連結的異常(異常的 __cause____context__ 屬性),就像直譯器在列印未處理的異常時所做的那樣。

在 3.5 版本中更改: 忽略 etype 引數,並從 value 的型別推斷出來。

在 3.10 版本中更改: etype 引數已重新命名為 exc,現在是僅限位置的。

traceback.print_exc(limit=None, file=None, chain=True)

這是 print_exception(sys.exception(), limit, file, chain) 的簡寫。

traceback.print_last(limit=None, file=None, chain=True)

這是 print_exception(sys.last_exc, limit, file, chain) 的簡寫形式。一般來說,它只有在異常到達互動式提示符後才起作用(請參閱 sys.last_exc)。

traceback.print_stack(f=None, limit=None, file=None)

如果 limit 為正數,則列印最多 limit 個堆疊跟蹤條目(從呼叫點開始)。否則,列印最後 abs(limit) 個條目。如果省略 limit 或為 None,則列印所有條目。可選引數 f 可用於指定要開始的備用 堆疊幀。可選引數 file 的含義與 print_tb() 中的含義相同。

在 3.5 版本中更改: 添加了負 limit 支援。

traceback.extract_tb(tb, limit=None)

返回一個 StackSummary 物件,該物件表示從 回溯物件 tb 中提取的“預處理”堆疊跟蹤條目列表。它對於堆疊跟蹤的替代格式很有用。可選引數 limit 的含義與 print_tb() 中的含義相同。“預處理”堆疊跟蹤條目是一個 FrameSummary 物件,其中包含屬性 filenamelinenonameline,這些屬性表示通常為堆疊跟蹤列印的資訊。

traceback.extract_stack(f=None, limit=None)

從當前的 堆疊幀 中提取原始回溯。返回值與 extract_tb() 的格式相同。可選引數 flimit 的含義與 print_stack() 中的含義相同。

traceback.print_list(extracted_list, file=None)

將由 extract_tb()extract_stack() 返回的元組列表作為格式化的堆疊跟蹤列印到給定的檔案。如果 fileNone,則將輸出寫入 sys.stderr

traceback.format_list(extracted_list)

給定一個元組列表或由 extract_tb()extract_stack() 返回的 FrameSummary 物件,返回一個準備列印的字串列表。結果列表中的每個字串都對應於引數列表中具有相同索引的項。每個字串都以換行符結尾;對於那些源文字行不是 None 的項,字串也可能包含內部換行符。

traceback.format_exception_only(exc, /, [value, ]*, show_group=False)

使用異常值(例如由 sys.last_value 給出的值)格式化回溯的異常部分。返回值是一個字串列表,每個字串都以換行符結尾。該列表包含異常的訊息,通常是一個字串;但是,對於 SyntaxError 異常,它包含多行,這些行(在列印時)顯示有關語法錯誤發生位置的詳細資訊。在訊息之後,該列表包含異常的 notes

自 Python 3.10 起,可以傳遞異常物件作為第一個引數,而不是傳遞 value。如果提供了 value,則為了提供向後相容性,將忽略第一個引數。

show_groupTrue 且異常是 BaseExceptionGroup 的例項時,巢狀異常也將被遞迴包含,並帶有相對於其巢狀深度的縮排。

在 3.10 版本中更改: etype 引數已重新命名為 exc,現在是僅限位置的。

在 3.11 版本中更改: 現在,返回的列表包含附加到異常的任何 notes

在 3.13 版本中更改: 添加了 show_group 引數。

traceback.format_exception(exc, /, [value, tb, ]limit=None, chain=True)

格式化堆疊跟蹤和異常資訊。引數的含義與 print_exception() 的對應引數的含義相同。返回值是一個字串列表,每個字串都以換行符結尾,其中一些包含內部換行符。當這些行被連線和列印時,列印的文字與 print_exception() 完全相同。

在 3.5 版本中更改: 忽略 etype 引數,並從 value 的型別推斷出來。

在 3.10 版本中更改: 此函式的行為和簽名已修改為與 print_exception() 匹配。

traceback.format_exc(limit=None, chain=True)

此函式類似於 print_exc(limit),但返回的是字串而不是列印到檔案。

traceback.format_tb(tb, limit=None)

format_list(extract_tb(tb, limit)) 的簡寫形式。

traceback.format_stack(f=None, limit=None)

format_list(extract_stack(f, limit)) 的簡寫形式。

traceback.clear_frames(tb)

透過呼叫每個幀物件clear()方法,清除回溯 *tb* 中所有堆疊幀的區域性變數。

3.4 版本新增。

traceback.walk_stack(f)

從給定幀開始,按照 f.f_back 遍歷堆疊,併為每個幀生成幀和行號。如果 *f* 為 None,則使用當前堆疊。此輔助函式與 StackSummary.extract() 一起使用。

3.5 版本新增。

traceback.walk_tb(tb)

按照 tb_next 遍歷回溯,併為每個幀生成幀和行號。此輔助函式與 StackSummary.extract() 一起使用。

3.5 版本新增。

TracebackException 物件

3.5 版本新增。

TracebackException 物件由實際的異常建立,用於捕獲資料以供後續列印。它們提供了一種更輕量級的方法來儲存此資訊,避免持有對 回溯 物件的引用。此外,與上述模組級函式相比,它們公開了更多配置輸出的選項。

class traceback.TracebackException(exc_type, exc_value, exc_traceback, *, limit=None, lookup_lines=True, capture_locals=False, compact=False, max_group_width=15, max_group_depth=10)

捕獲異常以便稍後呈現。 *limit*、*lookup_lines* 和 *capture_locals* 的含義與 StackSummary 類相同。

如果 *compact* 為 true,則只在類屬性中儲存 TracebackExceptionformat() 方法所需的資料。 特別是,只有當 __cause__None__suppress_context__ 為 false 時,才會計算 __context__ 欄位。

請注意,當捕獲區域性變數時,它們也會顯示在回溯中。

*max_group_width* 和 *max_group_depth* 控制異常組的格式(請參閱 BaseExceptionGroup)。深度是指組的巢狀級別,而寬度是指單個異常組的異常陣列的大小。當超出任一限制時,格式化輸出會被截斷。

在 3.10 版本中變更: 添加了 *compact* 引數。

在 3.11 版本中變更: 添加了 *max_group_width* 和 *max_group_depth* 引數。

__cause__

原始 __cause__TracebackException

__context__

原始 __context__TracebackException

exceptions

如果 self 表示一個 ExceptionGroup,則此欄位包含一個 TracebackException 例項列表,表示巢狀的異常。否則為 None

3.11 版本新增。

__suppress_context__

原始異常中的 __suppress_context__ 值。

__notes__

原始異常中的 __notes__ 值,如果異常沒有任何註釋,則為 None。如果它不是 None,則在異常字串之後格式化在回溯中。

3.11 版本新增。

stack

表示回溯的 StackSummary

exc_type

原始回溯的類。

3.13 版本起已棄用。

exc_type_str

原始異常的類的字串顯示。

3.13 版本新增。

filename

對於語法錯誤 - 發生錯誤的檔名。

lineno

對於語法錯誤 - 發生錯誤的行號。

end_lineno

對於語法錯誤 - 發生錯誤的結束行號。如果不存在,則可以為 None

在版本 3.10 中新增。

text

對於語法錯誤 - 發生錯誤的文字。

offset

對於語法錯誤 - 錯誤在文字中發生的偏移量。

end_offset

對於語法錯誤 - 錯誤在文字中發生的結束偏移量。如果不存在,則可以為 None

在版本 3.10 中新增。

msg

對於語法錯誤 - 編譯器錯誤訊息。

classmethod from_exception(exc, *, limit=None, lookup_lines=True, capture_locals=False)

捕獲異常以供稍後渲染。limitlookup_linescapture_localsStackSummary 類相同。

請注意,當捕獲區域性變數時,它們也會顯示在回溯中。

print(*, file=None, chain=True)

format() 返回的異常資訊列印到 file (預設 sys.stderr)。

3.11 版本新增。

format(*, chain=True)

格式化異常。

如果 chain 不是 True,則不會格式化 __cause____context__

返回值是一個字串生成器,每個字串都以換行符結尾,並且有些字串包含內部換行符。print_exception() 是對此方法的包裝,它只是將行列印到檔案中。

format_exception_only(*, show_group=False)

格式化回溯的異常部分。

返回值是一個字串生成器,每個字串都以換行符結尾。

show_groupFalse 時,生成器會發出異常的訊息,後跟其註釋(如果有)。異常訊息通常是單個字串;但是,對於 SyntaxError 異常,它由多行組成,這些行(列印時)顯示有關語法錯誤發生位置的詳細資訊。

show_groupTrue 且異常是 BaseExceptionGroup 的例項時,巢狀異常也將被遞迴包含,並帶有相對於其巢狀深度的縮排。

在 3.11 版本中更改: 異常的 notes 現在包含在輸出中。

在 3.13 版本中更改: 添加了 show_group 引數。

StackSummary 物件

3.5 版本新增。

StackSummary 物件表示準備好格式化的呼叫堆疊。

class traceback.StackSummary
classmethod extract(frame_gen, *, limit=None, lookup_lines=True, capture_locals=False)

從幀生成器(例如由 walk_stack()walk_tb() 返回的生成器)構造 StackSummary 物件。

如果提供了 limit,則僅從 frame_gen 中獲取這麼多幀。如果 lookup_linesFalse,則返回的 FrameSummary 物件將不會讀取它們的行,從而降低建立 StackSummary 的成本(如果它可能實際上不會被格式化,這可能會很有價值)。如果 capture_localsTrue,則每個 FrameSummary 中的區域性變數將作為物件表示形式捕獲。

在 3.12 版本中更改: capture_localsTrue 時,從區域性變數上的 repr() 引發的異常不再傳播給呼叫者。

classmethod from_list(a_list)

從提供的 FrameSummary 物件列表或舊式元組列表構造 StackSummary 物件。每個元組都應該是包含 filenamelinenonameline 作為元素的 4 元組。

format()

返回準備列印的字串列表。結果列表中的每個字串都對應於堆疊中的單個 frame。每個字串都以換行符結尾;這些字串也可能包含內部換行符,對於那些帶有原始碼文字行的專案。

對於相同幀和行的長序列,會顯示前幾個重複項,後跟一個摘要行,說明進一步重複的確切次數。

在 3.6 版本中更改: 現在會縮寫重複幀的長序列。

format_frame_summary(frame_summary)

返回一個用於列印堆疊中涉及的 frames 之一的字串。對於要由 StackSummary.format() 列印的每個 FrameSummary 物件,都會呼叫此方法。如果它返回 None,則該幀將從輸出中省略。

3.11 版本新增。

FrameSummary 物件

3.5 版本新增。

FrameSummary 物件表示 traceback 中的單個 frame

class traceback.FrameSummary(filename, lineno, name, lookup_line=True, locals=None, line=None)

表示在格式化或列印的回溯或堆疊中的單個。它可以選擇性地包含幀的區域性變數的字串化版本。如果 lookup_lineFalse,則在 FrameSummary 訪問 line 屬性(當將其轉換為 tuple 時也會發生)之前,不會查詢原始碼。可以直接提供 line,這將阻止所有行查詢發生。locals 是一個可選的區域性變數對映,如果提供,變量表示形式將儲存在摘要中以供稍後顯示。

FrameSummary 例項具有以下屬性

filename

此幀的原始碼檔名。等效於訪問 f.f_code.co_filename幀物件 f 上。

lineno

此幀的原始碼行號。

name

等效於訪問 f.f_code.co_name幀物件 f 上。

line

表示此幀的原始碼的字串,其中刪除了開頭和結尾的空格。如果原始碼不可用,則為 None

使用模組級函式的示例

這個簡單的示例實現了一個基本的讀取-求值-列印迴圈,類似於(但不如)標準的 Python 互動式直譯器迴圈。有關直譯器迴圈的更完整實現,請參閱 code 模組。

import sys, traceback

def run_user_code(envdir):
    source = input(">>> ")
    try:
        exec(source, envdir)
    except Exception:
        print("Exception in user code:")
        print("-"*60)
        traceback.print_exc(file=sys.stdout)
        print("-"*60)

envdir = {}
while True:
    run_user_code(envdir)

以下示例演示了列印和格式化異常和回溯的不同方法

import sys, traceback

def lumberjack():
    bright_side_of_life()

def bright_side_of_life():
    return tuple()[0]

try:
    lumberjack()
except IndexError as exc:
    print("*** print_tb:")
    traceback.print_tb(exc.__traceback__, limit=1, file=sys.stdout)
    print("*** print_exception:")
    traceback.print_exception(exc, limit=2, file=sys.stdout)
    print("*** print_exc:")
    traceback.print_exc(limit=2, file=sys.stdout)
    print("*** format_exc, first and last line:")
    formatted_lines = traceback.format_exc().splitlines()
    print(formatted_lines[0])
    print(formatted_lines[-1])
    print("*** format_exception:")
    print(repr(traceback.format_exception(exc)))
    print("*** extract_tb:")
    print(repr(traceback.extract_tb(exc.__traceback__)))
    print("*** format_tb:")
    print(repr(traceback.format_tb(exc.__traceback__)))
    print("*** tb_lineno:", exc.__traceback__.tb_lineno)

示例的輸出將類似於這樣

*** print_tb:
  File "<doctest...>", line 10, in <module>
    lumberjack()
    ~~~~~~~~~~^^
*** print_exception:
Traceback (most recent call last):
  File "<doctest...>", line 10, in <module>
    lumberjack()
    ~~~~~~~~~~^^
  File "<doctest...>", line 4, in lumberjack
    bright_side_of_life()
    ~~~~~~~~~~~~~~~~~~~^^
IndexError: tuple index out of range
*** print_exc:
Traceback (most recent call last):
  File "<doctest...>", line 10, in <module>
    lumberjack()
    ~~~~~~~~~~^^
  File "<doctest...>", line 4, in lumberjack
    bright_side_of_life()
    ~~~~~~~~~~~~~~~~~~~^^
IndexError: tuple index out of range
*** format_exc, first and last line:
Traceback (most recent call last):
IndexError: tuple index out of range
*** format_exception:
['Traceback (most recent call last):\n',
 '  File "<doctest default[0]>", line 10, in <module>\n    lumberjack()\n    ~~~~~~~~~~^^\n',
 '  File "<doctest default[0]>", line 4, in lumberjack\n    bright_side_of_life()\n    ~~~~~~~~~~~~~~~~~~~^^\n',
 '  File "<doctest default[0]>", line 7, in bright_side_of_life\n    return tuple()[0]\n           ~~~~~~~^^^\n',
 'IndexError: tuple index out of range\n']
*** extract_tb:
[<FrameSummary file <doctest...>, line 10 in <module>>,
 <FrameSummary file <doctest...>, line 4 in lumberjack>,
 <FrameSummary file <doctest...>, line 7 in bright_side_of_life>]
*** format_tb:
['  File "<doctest default[0]>", line 10, in <module>\n    lumberjack()\n    ~~~~~~~~~~^^\n',
 '  File "<doctest default[0]>", line 4, in lumberjack\n    bright_side_of_life()\n    ~~~~~~~~~~~~~~~~~~~^^\n',
 '  File "<doctest default[0]>", line 7, in bright_side_of_life\n    return tuple()[0]\n           ~~~~~~~^^^\n']
*** tb_lineno: 10

以下示例顯示了列印和格式化堆疊的不同方法

>>> import traceback
>>> def another_function():
...     lumberstack()
...
>>> def lumberstack():
...     traceback.print_stack()
...     print(repr(traceback.extract_stack()))
...     print(repr(traceback.format_stack()))
...
>>> another_function()
  File "<doctest>", line 10, in <module>
    another_function()
  File "<doctest>", line 3, in another_function
    lumberstack()
  File "<doctest>", line 6, in lumberstack
    traceback.print_stack()
[('<doctest>', 10, '<module>', 'another_function()'),
 ('<doctest>', 3, 'another_function', 'lumberstack()'),
 ('<doctest>', 7, 'lumberstack', 'print(repr(traceback.extract_stack()))')]
['  File "<doctest>", line 10, in <module>\n    another_function()\n',
 '  File "<doctest>", line 3, in another_function\n    lumberstack()\n',
 '  File "<doctest>", line 8, in lumberstack\n    print(repr(traceback.format_stack()))\n']

最後一個示例演示了最後幾個格式化函式

>>> import traceback
>>> traceback.format_list([('spam.py', 3, '<module>', 'spam.eggs()'),
...                        ('eggs.py', 42, 'eggs', 'return "bacon"')])
['  File "spam.py", line 3, in <module>\n    spam.eggs()\n',
 '  File "eggs.py", line 42, in eggs\n    return "bacon"\n']
>>> an_error = IndexError('tuple index out of range')
>>> traceback.format_exception_only(an_error)
['IndexError: tuple index out of range\n']

使用 TracebackException 的示例

有了輔助類,我們有更多的選擇

>>> import sys
>>> from traceback import TracebackException
>>>
>>> def lumberjack():
...     bright_side_of_life()
...
>>> def bright_side_of_life():
...     t = "bright", "side", "of", "life"
...     return t[5]
...
>>> try:
...     lumberjack()
... except IndexError as e:
...     exc = e
...
>>> try:
...     try:
...         lumberjack()
...     except:
...         1/0
... except Exception as e:
...     chained_exc = e
...
>>> # limit works as with the module-level functions
>>> TracebackException.from_exception(exc, limit=-2).print()
Traceback (most recent call last):
  File "<python-input-1>", line 6, in lumberjack
    bright_side_of_life()
    ~~~~~~~~~~~~~~~~~~~^^
  File "<python-input-1>", line 10, in bright_side_of_life
    return t[5]
           ~^^^
IndexError: tuple index out of range

>>> # capture_locals adds local variables in frames
>>> TracebackException.from_exception(exc, limit=-2, capture_locals=True).print()
Traceback (most recent call last):
  File "<python-input-1>", line 6, in lumberjack
    bright_side_of_life()
    ~~~~~~~~~~~~~~~~~~~^^
  File "<python-input-1>", line 10, in bright_side_of_life
    return t[5]
           ~^^^
    t = ("bright", "side", "of", "life")
IndexError: tuple index out of range

>>> # The *chain* kwarg to print() controls whether chained
>>> # exceptions are displayed
>>> TracebackException.from_exception(chained_exc).print()
Traceback (most recent call last):
  File "<python-input-19>", line 4, in <module>
    lumberjack()
    ~~~~~~~~~~^^
  File "<python-input-8>", line 7, in lumberjack
    bright_side_of_life()
    ~~~~~~~~~~~~~~~~~~~^^
  File "<python-input-8>", line 11, in bright_side_of_life
    return t[5]
           ~^^^
IndexError: tuple index out of range

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<python-input-19>", line 6, in <module>
    1/0
    ~^~
ZeroDivisionError: division by zero

>>> TracebackException.from_exception(chained_exc).print(chain=False)
Traceback (most recent call last):
  File "<python-input-19>", line 6, in <module>
    1/0
    ~^~
ZeroDivisionError: division by zero