bdb --- 偵錯程式框架

原始碼: Lib/bdb.py


bdb 模組處理基本的偵錯程式功能,例如設定斷點或透過偵錯程式管理執行。

定義了以下異常:

exception bdb.BdbQuit

Bdb 類引發的異常,用於退出偵錯程式。

bdb 模組還定義了兩個類:

class bdb.Breakpoint(self, file, line, temporary=False, cond=None, funcname=None)

這個類實現了臨時斷點、忽略次數、停用和(重新)啟用以及條件斷點。

斷點透過名為 bpbynumber 的列表按編號索引,並透過 (file, line) 對透過 bplist 索引。前者指向 Breakpoint 類的單個例項。後者指向一個這類例項的列表,因為每行可能有多個斷點。

建立斷點時,其關聯的 檔名 應為規範形式。如果定義了 funcname,則當該函式的第一行被執行時,斷點 命中 將被計數。一個 條件 斷點總是會計算一次 命中

Breakpoint 例項具有以下方法:

deleteMe()

從與檔案/行關聯的列表中刪除斷點。如果它是該位置的最後一個斷點,它還會刪除檔案/行的條目。

enable()

將斷點標記為啟用。

disable()

將斷點標記為停用。

bpformat()

返回一個包含所有關於斷點資訊的字串,並進行良好格式化:

  • 斷點編號。

  • 臨時狀態(del 或 keep)。

  • 檔案/行位置。

  • 中斷條件。

  • 要忽略的次數。

  • 命中次數。

在 3.2 版本加入。

bpprint(out=None)

bpformat() 的輸出列印到檔案 *out*,如果 *out* 為 None,則列印到標準輸出。

Breakpoint 例項具有以下屬性:

file

Breakpoint 的檔名。

line

fileBreakpoint 的行號。

temporary

如果位於(檔案,行)的 Breakpoint 是臨時的,則為 True

cond

評估位於(檔案,行)的 Breakpoint 的條件。

funcname

函式名,用於定義進入該函式時是否命中 Breakpoint

enabled

如果 Breakpoint 已啟用,則為 True

bpbynumber

單個 Breakpoint 例項的數字索引。

bplist

以 (file, line) 元組為索引的 Breakpoint 例項的字典。

ignore

忽略一個 Breakpoint 的次數。

hits

一個 Breakpoint 被命中的次數計數。

class bdb.Bdb(skip=None, backend='settrace')

Bdb 類作為一個通用的 Python 偵錯程式基類。

這個類負責處理跟蹤工具的細節;派生類應該實現使用者互動。標準偵錯程式類 (pdb.Pdb) 就是一個例子。

如果提供了 *skip* 引數,它必須是一個 glob 風格模組名模式的可迭代物件。偵錯程式將不會進入源自於匹配這些模式之一的模組的幀。一個幀是否被認為源自某個特定模組是由該幀的全域性變數中的 __name__ 決定的。

*backend* 引數指定用於 Bdb 的後端。它可以是 'settrace''monitoring''settrace' 使用 sys.settrace(),它具有最好的向後相容性。 'monitoring' 後端使用 Python 3.12 中引入的新 sys.monitoring,它可以更高效,因為它能停用未使用的事件。我們試圖為兩個後端保持完全相同的介面,但存在一些差異。鼓勵偵錯程式開發者使用 'monitoring' 後端以獲得更好的效能。

在 3.1 版本發生變更: 添加了 *skip* 形參。

在 3.14 版本發生變更: 添加了 *backend* 形參。

以下 Bdb 的方法通常不需要被重寫。

canonic(filename)

返回 *filename* 的規範形式。

對於真實的檔名,規範形式是一個依賴於作業系統、大小寫規範化絕對 路徑。一個帶有尖括號的 *filename*,例如在互動模式下生成的 "<stdin>",會原樣返回。

start_trace(self)

開始跟蹤。對於 'settrace' 後端,此方法等同於 sys.settrace(self.trace_dispatch)

在 3.14 版本加入。

stop_trace(self)

停止跟蹤。對於 'settrace' 後端,此方法等同於 sys.settrace(None)

在 3.14 版本加入。

reset()

設定 botframe, stopframe, returnframequitting 屬性,其值準備好開始除錯。

trace_dispatch(frame, event, arg)

此函式作為被除錯幀的跟蹤函式被安裝。它的返回值是新的跟蹤函式(在大多數情況下,就是它本身)。

預設實現根據即將執行的事件型別(作為字串傳遞)來決定如何分派一個幀。*event* 可以是以下之一:

  • "line": 即將執行一行新程式碼。

  • "call": 即將呼叫一個函式,或進入另一個程式碼塊。

  • "return": 一個函式或其他程式碼塊即將返回。

  • "exception": 發生了一個異常。

  • "c_call": 即將呼叫一個 C 函式。

  • "c_return": 一個 C 函式已返回。

  • "c_exception": 一個 C 函式引發了異常。

對於 Python 事件,會呼叫專門的函式(見下文)。對於 C 事件,不採取任何操作。

*arg* 引數取決於前一個事件。

有關跟蹤函式的更多資訊,請參閱 sys.settrace() 的文件。有關程式碼和幀物件的更多資訊,請參閱 標準型別層級結構

dispatch_line(frame)

如果偵錯程式應該在當前行停止,則呼叫 user_line() 方法(應在子類中重寫)。如果 quitting 標誌被設定(可以從 user_line() 中設定),則引發 BdbQuit 異常。返回對 trace_dispatch() 方法的引用,以便在該作用域中進行進一步的跟蹤。

dispatch_call(frame, arg)

如果偵錯程式應該在此函式呼叫處停止,則呼叫 user_call() 方法(應在子類中重寫)。如果 quitting 標誌被設定(可以從 user_call() 中設定),則引發 BdbQuit 異常。返回對 trace_dispatch() 方法的引用,以便在該作用域中進行進一步的跟蹤。

dispatch_return(frame, arg)

如果偵錯程式應該在此函式返回處停止,則呼叫 user_return() 方法(應在子類中重寫)。如果 quitting 標誌被設定(可以從 user_return() 中設定),則引發 BdbQuit 異常。返回對 trace_dispatch() 方法的引用,以便在該作用域中進行進一步的跟蹤。

dispatch_exception(frame, arg)

如果偵錯程式應該在此異常處停止,則呼叫 user_exception() 方法(應在子類中重寫)。如果 quitting 標誌被設定(可以從 user_exception() 中設定),則引發 BdbQuit 異常。返回對 trace_dispatch() 方法的引用,以便在該作用域中進行進一步的跟蹤。

通常派生類不會重寫以下方法,但如果它們想重新定義停止和斷點的定義,則可以這樣做。

is_skipped_line(module_name)

如果 *module_name* 匹配任何跳過模式,則返回 True

stop_here(frame)

如果 *frame* 在堆疊中低於起始幀,則返回 True

break_here(frame)

如果此行存在有效斷點,則返回 True

檢查是否存在行或函式斷點並且生效。根據來自 effective() 的資訊刪除臨時斷點。

break_anywhere(frame)

如果 *frame* 的檔名存在任何斷點,則返回 True

派生類應重寫這些方法以控制偵錯程式操作。

user_call(frame, argument_list)

如果中斷可能在被呼叫函式內部停止,則從 dispatch_call() 中呼叫。

*argument_list* 不再使用,將始終為 None。保留此引數是為了向後相容。

user_line(frame)

stop_here()break_here() 返回 True 時,從 dispatch_line() 中呼叫。

user_return(frame, return_value)

stop_here() 返回 True 時,從 dispatch_return() 中呼叫。

user_exception(frame, exc_info)

stop_here() 返回 True 時,從 dispatch_exception() 中呼叫。

do_clear(arg)

處理當一個斷點是臨時斷點時,必須如何移除它。

此方法必須由派生類實現。

派生類和客戶端可以呼叫以下方法來影響單步執行狀態。

set_step()

在執行一行程式碼後停止。

set_next(frame)

在給定幀之內或之下的下一行停止。

set_return(frame)

從給定幀返回時停止。

set_until(frame, lineno=None)

當達到行號大於當前行的行,或從當前幀返回時停止。

set_trace([frame])

從 *frame* 開始除錯。如果未指定 *frame*,則從呼叫者的幀開始除錯。

在 3.13 版本發生變更: set_trace() 將立即進入偵錯程式,而不是在下一行待執行的程式碼處。

set_continue()

僅在斷點處或完成時停止。如果沒有斷點,將系統跟蹤函式設定為 None

set_quit()

quitting 屬性設定為 True。這會在下一次呼叫 dispatch_*() 方法之一時引發 BdbQuit

派生類和客戶端可以呼叫以下方法來操作斷點。如果出現問題,這些方法返回包含錯誤訊息的字串;如果一切正常,則返回 None

set_break(filename, lineno, temporary=False, cond=None, funcname=None)

設定一個新斷點。如果作為引數傳遞的 *filename* 中不存在 *lineno* 行,則返回錯誤訊息。*filename* 應為規範形式,如 canonic() 方法中所述。

clear_break(filename, lineno)

刪除 *filename* 和 *lineno* 中的斷點。如果未設定任何斷點,則返回錯誤訊息。

clear_bpbynumber(arg)

刪除在 Breakpoint.bpbynumber 中索引為 *arg* 的斷點。如果 *arg* 不是數字或超出範圍,則返回錯誤訊息。

clear_all_file_breaks(filename)

刪除 *filename* 中的所有斷點。如果未設定任何斷點,則返回錯誤訊息。

clear_all_breaks()

刪除所有現有的斷點。如果沒有設定斷點,則返回錯誤訊息。

get_bpbynumber(arg)

返回由給定編號指定的斷點。如果 *arg* 是字串,它將被轉換為數字。如果 *arg* 是非數字字串,或者給定的斷點從未存在或已被刪除,則引發 ValueError

在 3.2 版本加入。

get_break(filename, lineno)

如果在 *filename* 的 *lineno* 處存在斷點,則返回 True

get_breaks(filename, lineno)

返回 *filename* 中 *lineno* 處的所有斷點,如果未設定則返回空列表。

get_file_breaks(filename)

返回 *filename* 中的所有斷點,如果未設定則返回空列表。

get_all_breaks()

返回所有已設定的斷點。

派生類和客戶端可以呼叫以下方法來停用和重啟事件,以獲得更好的效能。這些方法僅在使用 'monitoring' 後端時有效。

disable_current_event()

停用當前事件,直到下次呼叫 restart_events()。當偵錯程式對當前行不感興趣時,這很有用。

在 3.14 版本加入。

restart_events()

重新啟動所有已停用的事件。此函式在呼叫 user_* 方法之後,會在 dispatch_* 方法中自動呼叫。如果 dispatch_* 方法沒有被重寫,已停用的事件將在每次使用者互動後重新啟動。

在 3.14 版本加入。

派生類和客戶端可以呼叫以下方法來獲取表示堆疊跟蹤的資料結構。

get_stack(f, t)

返回堆疊跟蹤中的 (frame, lineno) 元組列表和一個大小。

最近呼叫的幀在列表的最後。大小是偵錯程式被呼叫處的幀以下的幀數。

format_stack_entry(frame_lineno, lprefix=': ')

返回一個包含堆疊條目資訊的字串,堆疊條目是一個 (frame, lineno) 元組。返回的字串包含:

  • 包含該幀的規範檔案名。

  • 函式名或 "<lambda>"

  • 輸入引數。

  • 返回值。

  • 程式碼行(如果存在)。

以下兩個方法可以由客戶端呼叫,以使用偵錯程式來除錯一個以字串形式給出的 語句

run(cmd, globals=None, locals=None)

透過 exec() 函式除錯一個語句。*globals* 預設為 __main__.__dict__,*locals* 預設為 *globals*。

runeval(expr, globals=None, locals=None)

透過 eval() 函式除錯一個表示式。*globals* 和 *locals* 的含義與 run() 中的相同。

runctx(cmd, globals, locals)

為了向後相容。呼叫 run() 方法。

runcall(func, /, *args, **kwds)

除錯單個函式呼叫,並返回其結果。

最後,該模組定義了以下函式:

bdb.checkfuncname(b, frame)

根據 Breakpoint *b* 的設定方式,返回是否應該在此處中斷。

如果它是透過行號設定的,它會檢查 b.line 是否與 *frame* 中的行號相同。如果斷點是透過 函式名 設定的,我們必須檢查我們是否在正確的 *frame*(正確的函式)中,以及我們是否在其第一個可執行行上。

bdb.effective(file, line, frame)

返回 (活動斷點, 刪除臨時標誌)(None, None) 作為要操作的斷點。

*活動斷點*是 bplist 中針對 (file, line)(必須存在)的第一個條目,該條目是 enabled 的,checkfuncname() 對其為真,並且既沒有為假的 條件,也沒有正的 ignore 計數。表示應刪除臨時斷點的*標誌*僅在無法評估 cond 時為 False(在這種情況下,ignore 計數被忽略)。

如果不存在這樣的條目,則返回 (None, None)

bdb.set_trace()

從呼叫者的幀開始,使用一個 Bdb 例項進行除錯。