traceback
— 列印或檢索棧回溯¶
原始碼: Lib/traceback.py
此模組提供了用於提取、格式化和列印 Python 程式棧跟蹤的標準介面。它比直譯器的預設回溯顯示更靈活,因此可以配置輸出的某些方面。最後,它包含一個實用工具,用於捕獲有關異常的足夠資訊以便以後列印,而無需儲存對實際異常的引用。由於異常可能是大型物件圖的根,因此此實用工具可以顯著改善記憶體管理。
該模組使用回溯物件——這些是 types.TracebackType
型別的物件,它們被分配給 BaseException
例項的 __traceback__
欄位。
參見
- 模組
faulthandler
用於在故障、超時或使用者訊號時顯式轉儲 Python 回溯。
- 模組
pdb
Python 程式的互動式原始碼偵錯程式。
模組的 API 可分為兩部分
提供基本功能的模組級函式,這些函式對於互動式檢查異常和回溯非常有用。
TracebackException
類及其輔助類StackSummary
和FrameSummary
。它們提供更大的輸出靈活性,並且能夠儲存必要的資訊以便稍後格式化,而無需持有對實際異常和回溯物件的引用。
3.13 版本新增: 輸出預設著色,並且可以透過環境變數控制。
模組級函式¶
- traceback.print_tb(tb, limit=None, file=None)¶
從 回溯物件 tb 中列印最多 limit 個棧跟蹤條目(從呼叫者幀開始),如果 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 起,可以不傳遞 value 和 tb,而是將一個異常物件作為第一個引數傳遞。如果提供了 value 和 tb,則第一個引數將被忽略以保持向後相容性。
可選的 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=limit, file=file, chain=chain)
的簡寫。
- traceback.print_last(limit=None, file=None, chain=True)¶
這是
print_exception(sys.last_exc, limit=limit, file=file, chain=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
物件,包含filename
、lineno
、name
和line
屬性,這些屬性表示通常為棧跟蹤列印的資訊。
- traceback.extract_stack(f=None, limit=None)¶
從當前 棧幀 中提取原始回溯。返回值與
extract_tb()
具有相同的格式。可選的 f 和 limit 引數與print_stack()
的含義相同。
- traceback.print_list(extracted_list, file=None)¶
將
extract_tb()
或extract_stack()
返回的元組列表作為格式化的棧跟蹤列印到給定檔案。如果 file 為None
,則輸出寫入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_group 為
True
且異常是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.walk_stack(f)¶
從給定幀開始,按照
f.f_back
遍歷棧,為每個幀生成幀和行號。如果 f 為None
,則使用當前棧。此輔助函式與StackSummary.extract()
一起使用。在 3.5 版本加入。
3.14 版本中有所改變: 此函式以前返回一個生成器,該生成器在首次迭代時會遍歷棧。現在返回的生成器是呼叫
walk_stack
時的棧狀態。
- 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,則只有
TracebackException
的format()
方法所需的資料才會儲存在類屬性中。特別是,只有當__cause__
為None
且__suppress_context__
為 false 時,才會計算__context__
欄位。請注意,當捕獲區域性變數時,它們也會顯示在回溯中。
max_group_width 和 max_group_depth 控制異常組的格式(參見
BaseExceptionGroup
)。深度指的是組的巢狀級別,寬度指的是單個異常組的異常陣列大小。當任何一個限制被超出時,格式化輸出將被截斷。3.10 版本中有所改變: 添加了 compact 引數。
3.11 版本中有所改變: 添加了 max_group_width 和 max_group_depth 引數。
- __context__¶
原始
__context__
的TracebackException
。
- exceptions¶
如果
self
表示一個ExceptionGroup
,則此欄位包含一個TracebackException
例項列表,表示巢狀異常。否則為None
。在 3.11 版本中新增。
- __suppress_context__¶
原始異常的
__suppress_context__
值。
- 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)¶
捕獲異常以供稍後渲染。limit、lookup_lines 和 capture_locals 的含義與
StackSummary
類相同。請注意,當捕獲區域性變數時,它們也會顯示在回溯中。
- format(*, chain=True)¶
格式化異常。
如果 chain 不為
True
,則__cause__
和__context__
將不會被格式化。返回值是一個字串生成器,每個字串以換行符結尾,有些字串包含內部換行符。
print_exception()
是此方法的包裝器,它只是將這些行列印到檔案。
- format_exception_only(*, show_group=False)¶
格式化回溯的異常部分。
返回值是一個字串生成器,每個字串以換行符結尾。
當 show_group 為
False
時,生成器會發出異常訊息,然後是其註釋(如果有的話)。異常訊息通常是一個字串;但是,對於SyntaxError
異常,它由多行組成,這些行(列印時)顯示有關語法錯誤發生位置的詳細資訊。當 show_group 為
True
且異常是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_lines 為
False
,則返回的FrameSummary
物件將尚未讀取其行,從而使建立StackSummary
的成本更低(如果它可能不會實際格式化,這可能很有價值)。如果 capture_locals 為True
,則每個FrameSummary
中的區域性變數將作為物件表示形式捕獲。3.12 版本中有所改變: 從區域性變數上的
repr()
引起的異常(當 capture_locals 為True
時)不再傳播給呼叫者。
- classmethod from_list(a_list)¶
從提供的
FrameSummary
物件列表或舊式元組列表構造一個StackSummary
物件。每個元組都應該是一個四元組,其中包含 filename、lineno、name、line 作為元素。
- format()¶
返回一個準備好列印的字串列表。結果列表中的每個字串對應於棧中的單個 幀。每個字串以換行符結尾;字串中也可能包含內部換行符,用於那些包含原始碼行的項。
對於相同幀和行的長序列,會顯示前幾次重複,然後是總結行,說明後續重複的確切次數。
3.6 版本中有所改變: 重複幀的長序列現在會縮寫。
- format_frame_summary(frame_summary)¶
返回一個字串,用於列印棧中涉及的 幀 中的一個。此方法由
StackSummary.format()
為每個要列印的FrameSummary
物件呼叫。如果它返回None
,則該幀將從輸出中省略。在 3.11 版本中新增。
FrameSummary
物件¶
在 3.5 版本加入。
一個 FrameSummary
物件表示 回溯 中的單個 幀。
- class traceback.FrameSummary(filename, lineno, name, *, lookup_line=True, locals=None, line=None, end_lineno=None, colno=None, end_colno=None)¶
表示正在格式化或列印的 回溯 或棧中的單個 幀。它可能可選地包含幀區域性變數的字串化版本。如果 lookup_line 為
False
,則在訪問FrameSummary
的line
屬性(這在將其轉換為tuple
時也會發生)之前,不會查詢原始碼。可以直接提供line
,這將完全阻止行查詢。locals 是一個可選的區域性變數對映,如果提供,變量表示將儲存在摘要中以供以後顯示。FrameSummary
例項具有以下屬性- filename¶
此幀原始碼的檔名。等同於訪問 幀物件 f 上的
f.f_code.co_filename
。
- lineno¶
此幀原始碼的行號。
- name¶
等同於訪問 幀物件 f 上的
f.f_code.co_name
。
- line¶
表示此幀原始碼的字串,已去除前導和尾隨空格。如果原始碼不可用,則為
None
。
- end_lineno¶
此幀原始碼的最後一行號。預設情況下,它設定為
lineno
,並且索引從 1 開始。3.13 版本中有所改變: 預設值從
None
更改為lineno
。
- colno¶
此幀原始碼的列號。預設情況下,它為
None
,並且索引從 0 開始。
- end_colno¶
此幀原始碼的最後一列號。預設情況下,它為
None
,並且索引從 0 開始。
使用模組級函式的示例¶
這個簡單的示例實現了一個基本的讀-求值-列印迴圈,類似於(但不如)標準 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