"pdb" --- Python 的调试器
*************************

**源代码：** Lib/pdb.py

======================================================================

"pdb" 模块定义了一个交互式源代码调试器，用于 Python 程序。它支持在源码
行间设置（有条件的）断点和单步执行，检视堆栈帧，列出源码列表，以及在任
何堆栈帧的上下文中运行任意 Python 代码。它还支持事后调试，可以在程序控
制下调用。

调试器是可扩展的——调试器实际被定义为 "Pdb" 类。该类目前没有文档，但通
过阅读源码很容易理解它。扩展接口使用了 "bdb" 和 "cmd" 模块。

调试器的提示符是 "(Pdb)"。在调试器的控制下运行程序的典型用法是:

   >>> import pdb
   >>> import mymodule
   >>> pdb.run('mymodule.test()')
   > <string>(0)?()
   (Pdb) continue
   > <string>(1)?()
   (Pdb) continue
   NameError: 'spam'
   > <string>(1)?()
   (Pdb)

在 3.3 版更改: 由 "readline" 模块实现的 Tab 补全可用于补全本模块的命令
和命令的参数，例如，Tab 补全会提供当前的全局变量和局部变量，用作 "p"
命令的参数。

也可以将 "pdb.py" 作为脚本调用，来调试其他脚本。例如:

   python3 -m pdb myscript.py

当作为脚本调用时，如果要调试的程序异常退出，pdb 调试将自动进入事后调试
。事后调试之后（或程序正常退出之后），pdb 将重新启动程序。自动重启会保
留 pdb 的状态（如断点），在大多数情况下，这比在退出程序的同时退出调试
器更加实用。

3.2 新版功能: "pdb.py" 现在接受 "-c" 选项，可以执行命令，这与将该命令
写入 ".pdbrc" 文件相同，请参阅 调试器命令。

3.7 新版功能: "pdb.py" 现在接受 "-m" 选项，该选项用于执行一个模块，类
似于 "python3 -m"。与脚本相同，调试器将暂停在待执行模块第一行前。

中断进入调试器的典型用法是插入:

   import pdb; pdb.set_trace()

到你想进入调试器的位置，再运行程序。 然后你可以单步执行这条语句之后的
代码，并使用 "continue" 命令来关闭调试器继续运行。

3.7 新版功能: 内置函数 "breakpoint()"，当以默认参数调用它时，可以用来
代替 "import pdb; pdb.set_trace()"。

检查已崩溃程序的典型用法是:

   >>> import pdb
   >>> import mymodule
   >>> mymodule.test()
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
     File "./mymodule.py", line 4, in test
       test2()
     File "./mymodule.py", line 3, in test2
       print(spam)
   NameError: spam
   >>> pdb.pm()
   > ./mymodule.py(3)test2()
   -> print(spam)
   (Pdb)

本模块定义了下列函数，每个函数进入调试器的方式略有不同：

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

   在调试器控制范围内执行 *statement* （以字符串或代码对象的形式提供）
   。调试器提示符会在执行代码前出现，你可以设置断点并键入 "continue"，
   也可以使用 "step" 或 "next" 逐步执行语句（上述所有命令在后文有说明
   ）。可选参数 *globals* 和 *locals* 指定代码执行环境，默认时使用
   "__main__" 模块的字典。（请参阅内置函数 "exec()" 或 "eval()" 的说明
   。）

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

   在调试器控制范围内执行 *expression* （以字符串或代码对象的形式提供
   ）。"runeval()" 返回时将返回表达式的值。本函数在其他方面与 "run()"
   类似。

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

   使用给定的参数调用 *function* （以函数或方法对象的形式提供，不能是
   字符串）。"runcall()" 返回的是所调用函数的返回值。调试器提示符将在
   进入函数后立即出现。

pdb.set_trace(*, header=None)

   在调用本函数的堆栈帧处进入调试器。用于硬编码一个断点到程序中的固定
   点处，即使该代码不在调试状态（如断言失败时）。如果传入 *header*，它
   将在调试开始前被打印到控制台。

   在 3.7 版更改: 仅关键字参数 *header*。

pdb.post_mortem(traceback=None)

   进入 *traceback* 对象的事后调试。如果没有给定 *traceback*，默认使用
   当前正在处理的异常之一（默认时，必须存在正在处理的异常）。

pdb.pm()

   在 "sys.last_traceback" 中查找 traceback，并进入其事后调试。

"run*" 函数和 "set_trace()" 都是别名，用于实例化 "Pdb" 类和调用同名方
法。如果要使用其他功能，则必须自己执行以下操作：

class pdb.Pdb(completekey='tab', stdin=None, stdout=None, skip=None, nosigint=False, readrc=True)

   "Pdb" 是调试器类。

   *completekey*、*stdin* 和 *stdout* 参数都会传递给底层的 "cmd.Cmd"
   类，请参考相应的描述。

   如果给出 *skip* 参数，则它必须是一个迭代器，可以迭代出 glob-style
   样式的模块名称。如果遇到匹配上述样式的模块，调试器将不会进入来自该
   模块的堆栈帧。 [1]

   默认情况下，当发出 "continue" 命令时，Pdb 将为 SIGINT 信号设置一个
   处理程序（SIGINT 信号是用户在控制台按 "Ctrl-C" 时发出的）。这使用户
   可以按 "Ctrl-C" 再次进入调试器。如果希望 Pdb 不要修改 SIGINT 处理程
   序，请将 *nosigint* 设置为 true。

   *readrc* 参数默认为 true，它控制 Pdb 是否从文件系统加载 .pdbrc 文件
   。

   启用跟踪且带有 *skip* 参数的调用示范:

      import pdb; pdb.Pdb(skip=['django.*']).set_trace()

   引发一个 审计事件 "pdb.Pdb"，没有附带参数。

   3.1 新版功能: *skip* 参数。

   3.2 新版功能: *nosigint* 参数。在这之前，Pdb 不为 SIGINT 设置处理程
   序。

   在 3.6 版更改: *readrc* 参数。

   run(statement, globals=None, locals=None)
   runeval(expression, globals=None, locals=None)
   runcall(function, *args, **kwds)
   set_trace()

      请参阅上文解释同名函数的文档。


调试器命令
==========

下方列出的是调试器可接受的命令。如下所示，大多数命令可以缩写为一个或两
个字母。如 "h(elp)" 表示可以输入 "h" 或 "help" 来输入帮助命令（但不能
输入 "he" 或 "hel"，也不能是 "H" 或 "Help" 或 "HELP"）。命令的参数必须
用空格（空格符或制表符）分隔。在命令语法中，可选参数括在方括号 ("[]")
中，使用时请勿输入方括号。命令语法中的选择项由竖线 ("|") 分隔。

输入一个空白行将重复最后输入的命令。例外：如果最后一个命令是 "list" 命
令，则会列出接下来的 11 行。

调试器无法识别的命令将被认为是 Python 语句，并在正在调试的程序的上下文
中执行。Python 语句也可以用感叹号 ("!") 作为前缀。这是检查正在调试的程
序的强大方法，甚至可以修改变量或调用函数。当此类语句发生异常，将打印异
常名称，但调试器的状态不会改变。

调试器支持 别名。别名可以有参数，使得调试器对被检查的上下文有一定程度
的适应性。

在一行中可以输入多条命令，以 ";;" 分隔。 （不能使用单个 ";"，因为它已
被用作传给 Python 解析器的一行中的多条命令的分隔符。） 命令切分所用的
方式没有任何智能可言；输入总是会在第一个 ";;" 对上被切分，即使它位于带
引号的字符串中。 对于带有双分号的字符串可以使用隐式字符串拼接 "';'';'"
或 "";"";"" 来变通处理。

如果文件 ".pdbrc" 存在于用户主目录或当前目录中，则将其读入并执行，等同
于在调试器提示符下键入该文件。这对于别名很有用。若两个文件都存在则首先
读取主目录中的文件，且本地文件可以覆盖其中定义的别名。

在 3.2 版更改: ".pdbrc" 现在可以包含继续调试的命令，如 "continue" 或
"next"。文件中的这些命令以前是无效的。

h(elp) [command]

   不带参数时，显示可用的命令列表。参数为 *command* 时，打印有关该命令
   的帮助。"help pdb" 显示完整文档（即 "pdb" 模块的文档字符串）。由于
   *command* 参数必须是标识符，因此要获取 "!" 的帮助必须输入 "help
   exec"。

w(here)

   打印堆栈回溯，最新一帧在底部。有一个箭头指向当前帧，该帧决定了大多
   数命令的上下文。

d(own) [count]

   在堆栈回溯中，将当前帧向下移动 *count* 级（默认为 1 级，移向更新的
   帧）。

u(p) [count]

   在堆栈回溯中，将当前帧向上移动 *count* 级（默认为 1 级，移向更老的
   帧）。

b(reak) [([filename:]lineno | function) [, condition]]

   如果带有 *lineno* 参数，则在当前文件相应行处设置一个断点。如果带有
   *function* 参数，则在该函数的第一条可执行语句处设置一个断点。行号可
   以加上文件名和冒号作为前缀，以在另一个文件（可能是尚未加载的文件）
   中设置一个断点。另一个文件将在 "sys.path" 范围内搜索。请注意，每个
   断点都分配有一个编号，其他所有断点命令都引用该编号。

   如果第二个参数存在，它应该是一个表达式，且它的计算值为 true 时断点
   才起作用。

   如果不带参数执行，将列出所有中断，包括每个断点、命中该断点的次数、
   当前的忽略次数以及关联的条件（如果有）。

tbreak [([filename:]lineno | function) [, condition]]

   临时断点，在第一次命中时会自动删除。它的参数与 "break" 相同。

cl(ear) [filename:lineno | bpnumber ...]

   如果参数是 *filename:lineno*，则清除此行上的所有断点。如果参数是空
   格分隔的断点编号列表，则清除这些断点。如果不带参数，则清除所有断点
   （但会先提示确认）。

disable [bpnumber ...]

   禁用断点，断点以空格分隔的断点编号列表给出。禁用断点表示它不会导致
   程序停止执行，但是与清除断点不同，禁用的断点将保留在断点列表中并且
   可以（重新）启用。

enable [bpnumber ...]

   启用指定的断点。

ignore bpnumber [count]

   为指定的断点编号设置忽略次数。如果省略 count，则忽略次数将设置为 0
   。忽略次数为 0 时断点将变为活动状态。如果为非零值，在每次达到断点，
   且断点未禁用，且关联条件计算值为 true 的情况下，该忽略次数会递减。

condition bpnumber [condition]

   为断点设置一个新 *condition*，它是一个表达式，且它的计算值为 true
   时断点才起作用。如果没有给出 *condition*，则删除现有条件，也就是将
   断点设为无条件。

commands [bpnumber]

   为编号是 *bpnumber* 的断点指定一系列命令。命令内容将显示在后续的几
   行中。输入仅包含 "end" 的行来结束命令列表。举个例子:

      (Pdb) commands 1
      (com) p some_variable
      (com) end
      (Pdb)

   要删除断点上的所有命令，请输入 "commands" 并立即以 "end" 结尾，也就
   是不指定任何命令。

   如果不带 *bpnumber* 参数，"commands" 作用于最后一个被设置的断点。

   可以为断点指定命令来重新启动程序。只需使用 "continue" 或 "step" 命
   令或其他可以继续运行程序的命令。

   如果指定了某个继续运行程序的命令（目前包括 "continue", "step",
   "next", "return", "jump", "quit" 及它们的缩写）将终止命令列表（就像
   该命令后紧跟着 end）。因为在任何时候继续运行下去（即使是简单的 next
   或 step），都可能会遇到另一个断点，该断点可能具有自己的命令列表，这
   导致要执行的列表含糊不清。

   如果在命令列表中加入 'silent' 命令，那么在该断点处停下时就不会打印
   常规信息。如果希望断点打印特定信息后继续运行，这可能是理想的。如果
   没有其他命令来打印一些信息，则看不到已达到断点的迹象。

s(tep)

   运行当前行，在第一个可以停止的位置（在被调用的函数内部或在当前函数
   的下一行）停下。

n(ext)

   继续运行，直到运行到当前函数的下一行，或当前函数返回为止。（ "next"
   和 "step" 之间的区别在于，"step" 进入被调用函数内部并停止，而
   "next" （几乎）全速运行被调用函数，仅在当前函数的下一行停止。）

unt(il) [lineno]

   如果不带参数，则继续运行，直到行号比当前行大时停止。

   如果带有行号，则继续运行，直到行号大于或等于该行号时停止。在这两种
   情况下，当前帧返回时也将停止。

   在 3.2 版更改: 允许明确给定行号。

r(eturn)

   继续运行，直到当前函数返回。

c(ont(inue))

   继续运行，仅在遇到断点时停止。

j(ump) lineno

   设置即将运行的下一行。仅可用于堆栈最底部的帧。它可以往回跳来再次运
   行代码，也可以往前跳来跳过不想运行的代码。

   需要注意的是，不是所有的跳转都是允许的 -- 例如，不能跳转到 "for" 循
   环的中间或跳出 "finally" 子句。

l(ist) [first[, last]]

   列出当前文件的源代码。如果不带参数，则列出当前行周围的 11 行，或延
   续前一次列出。如果用 "." 作为参数，则列出当前行周围的 11 行。如果带
   有一个参数，则列出那一行周围的 11 行。如果带有两个参数，则列出所给
   的范围中的代码；如果第二个参数小于第一个参数，则将其解释为列出行数
   的计数。

   当前帧中的当前行用 "->" 标记。如果正在调试异常，且最早抛出或传递该
   异常的行不是当前行，则那一行用 ">>" 标记。

   3.2 新版功能: ">>" 标记。

ll | longlist

   列出当前函数或帧的所有源代码。相关行的标记与 "list" 相同。

   3.2 新版功能.

a(rgs)

   打印当前函数的参数列表。

p expression

   在当前上下文中运行 *expression* 并打印它的值。

   注解:

     "print()" 也可以使用，但它不是一个调试器命令 --- 它执行 Python
     "print()" 函数。

pp expression

   与 "p" 命令类似，但表达式的值使用 "pprint" 模块美观地打印。

whatis expression

   打印 *expression* 的类型。

source expression

   尝试获取给定对象的源代码并显示出来。

   3.2 新版功能.

display [expression]

   如果表达式的值发生改变则显示它的值，每次将停止执行当前帧。

   不带表达式则列出当前帧的所有显示表达式。

   3.2 新版功能.

undisplay [expression]

   不再显示当前帧中的表达式。 不带表达式则清除当前帧的所有显示表达式。

   3.2 新版功能.

interact

   启动一个交互式解释器（使用 "code" 模块），它的全局命名空间将包含当
   前作用域中的所有（全局和局部）名称。

   3.2 新版功能.

alias [name [command]]

   创建一个标识为 *name* 的别名来执行 *command*。 执行的命令 *不可* 加
   上引号。 可替换形参可通过 "%1", "%2" 等来标示，而 "%*" 会被所有形参
   所替换。 如果没有给出命令，则会显示 *name* 的当前别名。 如果没有给
   出参数，则会列出所有别名。

   别名允许嵌套并可包含能在 pdb 提示符下合法输入的任何内容。 请注意内
   部 pdb 命令 *可以* 被别名所覆盖。 这样的命令将被隐藏直到别名被移除
   。 别名会递归地应用到命令行的第一个单词；行内的其他单词不会受影响。

   作为示例，这里列出了两个有用的别名（特别适合放在 ".pdbrc" 文件中）:

      # Print instance variables (usage "pi classInst")
      alias pi for k in %1.__dict__.keys(): print("%1.",k,"=",%1.__dict__[k])
      # Print instance variables in self
      alias ps pi self

unalias name

   删除指定的别名。

! statement

   在当前堆栈帧的上下文中执行 (单行) *statement*。 感叹号可以被省略，
   除非语句的第一个单词与调试器命令重名。 要设置全局变量，你可以在同一
   行上为赋值命令添加前缀的 "global" 语句，例如:

      (Pdb) global list_options; list_options = ['-l']
      (Pdb)

run [args ...]
restart [args ...]

   重启被调试的 Python 程序。 如果提供了参数，它会用 "shlex" 来拆分且
   拆分结果将被用作新的 "sys.argv"。 历史、中断点、动作和调试器选项将
   被保留。 "restart" 是 "run" 的一个别名。

q(uit)

   退出调试器。 被执行的程序将被中止。

debug code

   进入一个对代码参数执行步进的递归调试器（该参数是在当前环境中执行的
   任意表达式或语句）。

retval

   打印函数最后一次返回的返回值。

-[ 备注 ]-

[1] 一个帧是否会被认为源自特定模块是由帧全局变量 "__name__" 来决定的。
