traceback
— 列印或檢索堆疊回溯¶
原始碼: Lib/traceback.py
此模組提供了一個標準介面,用於提取、格式化和列印 Python 程式的堆疊跟蹤。 它比直譯器的預設回溯顯示更靈活,因此可以配置輸出的某些方面。 最後,它包含一個實用程式,用於捕獲有關異常的足夠資訊,以便稍後列印它,而無需儲存對實際異常的引用。 由於異常可能是大型物件圖的根,因此此實用程式可以顯著改善記憶體管理。
該模組使用 回溯物件 — 這些是 types.TracebackType
型別的物件,它們被分配給 __traceback__
BaseException
例項的欄位。
另請參閱
- 模組
faulthandler
用於在故障、超時後或在使用者訊號上顯式轉儲 Python 回溯。
- 模組
pdb
用於 Python 程式的互動式原始碼偵錯程式。
該模組的 API 可以分為兩部分
模組級函式提供基本功能,這對於互動式檢查異常和回溯非常有用。
TracebackException
類及其輔助類StackSummary
和FrameSummary
。 這些在生成的輸出中提供了更大的靈活性,並且能夠儲存稍後格式化所需的資訊,而無需保留對實際異常和回溯物件的引用。
模組級函式¶
- 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 開始,可以傳遞異常物件作為第一個引數,而不是傳遞 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, 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
物件,其中包含屬性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 版本新增。
- 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 版本中更改: 當 capture_locals 為
True
時,從區域性變數上的repr()
引發的異常不再傳播給呼叫者。
- classmethod from_list(a_list)¶
從提供的
FrameSummary
物件列表或舊式元組列表構造StackSummary
物件。每個元組都應該是包含 filename、lineno、name、line 作為元素的 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_line 為
False
,則在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