bdb --- 调试器框架

源代码: Lib/bdb.py


bdb 模块处理基本的调试器函数,例如设置中断点或通过调试器来管理执行。

定义了以下异常:

exception bdb.BdbQuit

Bdb 类引发用于退出调试器的异常。

bdb 模块还定义了两个类:

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

这个类实现了临时性中断点、忽略计数、禁用与(重新)启用,以及条件设置等。

中断点通过一个名为 bpbynumber 的列表基于数字并通过 bplist 基于 (file, line) 对进行索引。 前者指向一个 Breakpoint 类的单独实例。 后者指向一个由这种实例组成的列表,因为在每一行中可能存在多个中断点。

当创建一个中断点时,它所关联的文件名应当为规范的形式。 如果定义了 funcname,则当该函数的第一行被执行时将增加一次中断点命中计数。 带条件的中断点将总被增加一次计数。

Breakpoint 的实例具有下列方法:

deleteMe()

从关联到文件/行的列表中删除此中断点。 如果它是该位置上的最后一个中断点,还将删除相应的文件/行条目。

enable()

将此中断点标记为启用。

disable()

将此中断点标记为禁用。

bpformat()

返回一个带有关于此中断点的所有信息的,格式良好的字符串:

  • 此中断点的编号。

  • 它是否为临时性的。

  • 它的 file,line 位置。

  • 导致中断的条件。

  • 它是否必须在此后被忽略 N 次。

  • 此中断点的命中计数。

3.2 新版功能.

bpprint(out=None)

bpformat() 的输出打印到文件 out,或者如果为 None 则打印到标准输出。, to standard output.

class bdb.Bdb(skip=None)

Bdb 类是作为通用的 Python 调试器基类。

这个类负责追踪工具的细节;所派生的类应当实现用户交互。 标准调试器类 (pdb.Pdb) 就是一个例子。

如果给出了 skip 参数,它必须是一个包含 glob 风格的模块名称模式的可迭代对象。 调试器将不会步进到来自与这些模式相匹配的模块的帧。 一个帧是否会被视为来自特定的模块是由帧的 __name__ 全局变量来确定的。

3.1 新版功能: skip 参数。

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

canonic(filename)

用于获取规范形式文件名的辅助方法,也就是大小写规范的(在大小写不敏感文件系统上)绝对路径,并去除两边的尖括号。

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() 方法(该方法应当在子类中被重写)。 如果设置了 Bdb.quitting 旗标(可以通过 user_line() 设置)则将引发 BdbQuit 异常。 返回一个对 trace_dispatch() 方法的引用以便在该作用域内进一步地追踪。

dispatch_call(frame, arg)

如果调试器应当在此函数调用上停止,则发起调用 user_call() 方法(该方法应当在子类中被重写)。 如果设置了 Bdb.quitting 旗标(可以通过 user_call() 设置)则将引发 BdbQuit 异常。 返回一个对 trace_dispatch() 方法的引用以便在该作用域内进一步地追踪。

dispatch_return(frame, arg)

如果调试器应当在此函数返回时停止,则发起调用 user_return() 方法(该方法应当在子类中被重写)。 如果设置了 Bdb.quitting 旗标(可以通过 user_return() 设置)则将引发 BdbQuit 异常。 返回一个对 trace_dispatch() 方法的引用以便在该作用域内进一步地追踪。

dispatch_exception(frame, arg)

如果调试器应当在此异常上停止,则发起调用 user_exception() 方法(该方法应当在子类中被重写)。 如果设置了 Bdb.quitting 旗标(可以通过 user_exception() 设置)则将引发 BdbQuit 异常。 返回一个对 trace_dispatch() 方法的引用以便在该作用域内进一步地追踪。

通常情况下派生的类不会重写下列方法,但是如果想要重新定义停止和中断点的定义则可能会重写它们。

stop_here(frame)

此方法将检查调用栈中 frame 是否位于 botframe 的下方。 botframe 是调试开始所在的帧。

break_here(frame)

此方法将检查 frame 所属的文件名和行,或者至少当前函数中是否存在中断点。 如果中断点是临时性的,此方法将删除它。

break_anywhere(frame)

此方法将检查当前帧的文件名中是否存在中断点。

派生的类应当重写这些方法以获取调试器操作的控制权。

user_call(frame, argument_list)

当有可能在被调用函数内部的任何地方需要一个中断时此方法将从 dispatch_call() 被调用。

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)

当到达不大于当前行的行或当从当前帧返回时停止。

set_trace([frame])

frame 开始调试。 如果未指定 frame,则从调用者的帧开始调试。

set_continue()

仅在中断点上或是当结束时停止。 如果不存在中断点,则将系统追踪函数设为 None

set_quit()

quitting 属性设为 True。 这将在对某个 dispatch_*() 方法的下一次调用中引发 BdbQuit

派生的类和客户端可以调用下列方法来操纵中断点。 如果出现错误则这些方法将返回一个包含错误消息的字符串,或者如果一切正常则返回 None

set_break(filename, lineno, temporary=0, cond, funcname)

设置一个新的中断点。 如果对于作为参数传入的 filename 不存在 lineno,则返回一条错误消息。 filename 应为规范的形式,如在 canonic() 方法中描述的。

clear_break(filename, lineno)

删除位于 filenamelineno 上的中断点。 如果未设置过中断点。 则将返回一条错误消息。

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 上是否有中断点。

get_breaks(filename, lineno)

返回 filename 中在 lineno 上的所有中断点,或者如果未设置任何中断点则返回一个空列表。

get_file_breaks(filename)

返回 filename 中的所有中断点,或者如果未设置任何中断点则返回一个空列表。

get_all_breaks()

返回已设置的所有中断点。

派生类与客户端可以调用以下方法来获取一个代表栈回溯信息的数组结构。

get_stack(f, t)

获取一个帧及其所有上级(调用方)和下级帧的记录列表,以及上级部分的大小。

format_stack_entry(frame_lineno, lprefix=': ')

返回一个包含有关栈条目信息的字符串,由一个 (frame, lineno) 元组来标识:

  • 包含帧的规范形式的文件名。

  • 函数名称,或者 "<lambda>"

  • 输入参数。

  • 返回值。

  • 代码的行(如果存在)。

以下两个方法可由客户端调用以使用一个调试器来调试一条以字符串形式给出的 statement

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

调试一条通过 exec() 函数执行的语句。 globals 默认为 __main__.__dict__locals 默认为 globals

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

调试一条通过 eval() 函数执行的表达式。 globalslocals 的含义与在 run() 中的相同。

runctx(cmd, globals, locals)

为了保证向下兼容性。 调用 run() 方法。

runcall(func, *args, **kwds)

调试一个单独的函数调用,并返回其结果。

最后,这个模块定义了以下函数:

bdb.checkfuncname(b, frame)

检查是否应当在此中断,根据中断点 b 的设置方式。

如果是通过行号设置的,它将检查 b.line 是否与同样作为参数传入的帧中的行号一致。 如果中断点是通过函数名称设置的,则必须检查是否位于正确的帧(正确的函数)以及是否位于其中第一个可执行的行。

bdb.effective(file, line, frame)

确定在这一行代码中是否存在有效的(激活的)中断点。 返回一个包含中断点和表示是否可以删除临时中断点的布尔值的元组。 如果没有匹配的中断点则返回 (None, None)

bdb.set_trace()

使用一个来自调用方的帧的 Bdb 实例开始调试。