pdb --- Python 偵錯器

原始碼:Lib/pdb.py


pdb 模組定義了一個 Python 程式的互動式原始碼偵錯器。它支援在原始碼列層級 (source line level) 設定(條件式的)斷點 (breakpoint) 和單步執行、檢視 stack frame(堆疊框)、列出原始碼、以及在任何 stack frame 情境 (context) 中為任意 Python 程式碼求值 (evaluation)。它還支援事後偵錯 (post-mortem debugging),並可以在程式控制下呼叫。

偵錯器是可擴充的 —— 偵錯器實際被定義為 Pdb 類別。該類別目前沒有文件,但可以很容易地透過閱讀原始碼來理解它。擴充套件介面使用了 bdbcmd 模組。

也參考

faulthandler 模組

用於在出現故障時、超時 (timeout) 後或於接收到使用者訊號時,顯式地轉儲 (dump) Python 回溯 (traceback)。

traceback 模組

用於提取、格式化和印出 Python 程式 stack trace(堆疊追蹤)的標準介面。

自一個執行中程式切入偵錯器的典型用法為插入:

import pdb; pdb.set_trace()

或:

breakpoint()

到你想切入偵錯器的位置,然後執行程式,就可以單步執行上述陳述式之後的程式碼,並可以使用 continue 命令來離開偵錯器、繼續執行。

在 3.7 版的變更: 當使用預設值呼叫時,可以使用內建的 breakpoint() 來取代 import pdb; pdb.set_trace()

def double(x):
   breakpoint()
   return x * 2
val = 3
print(f"{val} * 2 is {double(val)}")

偵錯器的提示字元是 (Pdb),這表示你處於偵錯模式:

> ...(2)double()
-> breakpoint()
(Pdb) p x
3
(Pdb) continue
3 * 2 is 6

在 3.3 版的變更: 透過 readline 模組達成的 tab 補全可用於補全本模組的命令和命令的引數,例如會提供目前的全域和區域名稱以作為 p 命令的引數。

命令列介面

你還可以從命令列叫用 pdb 來偵錯其他腳本。例如:

python -m pdb [-c command] (-m module | -p pid | pyfile) [args ...]

當作為模組叫用時,如果被偵錯的程序不正常地退出,pdb 將自動進入事後偵錯。事後偵錯後(或程式正常退出後),pdb 將重新啟動程式。自動重新啟動會保留 pdb 的狀態(例如斷點),並且在大多數情況下比在程式退出時退出偵錯器更有用。

-c, --command <command>

就像在 .pdbrc 檔案中給定的那樣來執行命令;請參閱偵錯器命令

在 3.2 版的變更: 新增了 -c 選項。

-m <module>

以類似於 python -m 的方式來執行模組。與腳本一樣,偵錯器將在模組的第一列之前暫停執行。

在 3.7 版的變更: 新增了 -m 選項。

-p, --pid <pid>

Attach to the process with the specified PID.

在 3.14 版被加入.

To attach to a running Python process for remote debugging, use the -p or --pid option with the target process's PID:

python -m pdb -p 1234

備註

Attaching to a process that is blocked in a system call or waiting for I/O will only work once the next bytecode instruction is executed or when the process receives a signal.

在偵錯器控制下執行陳述式的典型用法是:

>>> import pdb
>>> def f(x):
...     print(1 / x)
>>> pdb.run("f(2)")
> <string>(1)<module>()
(Pdb) continue
0.5
>>>

檢查一個損壞程式的典型用法:

>>> import pdb
>>> def f(x):
...     print(1 / x)
...
>>> f(0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in f
ZeroDivisionError: division by zero
>>> pdb.pm()
> <stdin>(2)f()
(Pdb) p x
0
(Pdb)

在 3.13 版的變更: PEP 667 的實作意味著透過 pdb 進行的名稱賦予 (name assignments) 會立即影響有效作用域,即使在最佳化作用域內運作也是如此。

本模組定義了下列函式,每個函式進入偵錯器的方式略有不同:

pdb.run(statement, globals=None, locals=None)

在偵錯器控制下執行 statement(以字串或程式碼物件形式給定)。偵錯提示字元會在執行任何程式碼前出現;你可以設定斷點並輸入 continue,或也可以使用 stepnext 逐步執行陳述式(這些命令在下面都有說明)。可選引數 globalslocals 指定程式碼執行的環境;預設使用 __main__ 模組的字典。(請參閱內建函式 exec()eval() 的說明。)

pdb.runeval(expression, globals=None, locals=None)

在偵錯器控制下為 expression 求值(以字串或程式碼物件形式給定)。當 runeval() 回傳時,它回傳 expression 的值。除此之外,該函式與 run() 類似。

pdb.runcall(function, *args, **kwds)

使用給定的引數呼叫 function(只可以是函式或方法物件,不能是字串)。runcall() 回傳的是所呼叫函式的回傳值。偵錯器提示字元將在進入函式後立即出現。

pdb.set_trace(*, header=None, commands=None)

在呼叫此函式的 stack frame 進入偵錯器。用於在程式中給定之處寫死 (hard-code) 一個斷點,即便該程式碼不在偵錯狀態(如斷言失敗時)。如有給定 header,它將在偵錯正要開始前被印出到控制台。如果給定了 commands 引數,它會是在偵錯器啟動時要執行的命令清單。

在 3.7 版的變更: 僅限關鍵字引數 header

在 3.13 版的變更: set_trace() 將立即進入偵錯器,而不是在下一列要執行的程式碼中。

在 3.14 版被加入: commands 引數。

awaitable pdb.set_trace_async(*, header=None, commands=None)

async version of set_trace(). This function should be used inside an async function with await.

async def f():
    await pdb.set_trace_async()

await statements are supported if the debugger is invoked by this function.

在 3.14 版被加入.

pdb.post_mortem(t=None)

進入所給定例外或回溯物件的事後偵錯。如果沒有給定,預設使用目前正在處理的例外,或如果沒有例外則會引發 ValueError

在 3.13 版的變更: 新增對例外物件的支援。

pdb.pm()

進入在 sys.last_exc 中發現的例外的事後偵錯。

pdb.set_default_backend(backend)

There are two supported backends for pdb: 'settrace' and 'monitoring'. See bdb.Bdb for details. The user can set the default backend to use if none is specified when instantiating Pdb. If no backend is specified, the default is 'settrace'.

備註

breakpoint() and set_trace() will not be affected by this function. They always use 'monitoring' backend.

在 3.14 版被加入.

pdb.