bdb
--- 调试器框架¶
源代码: Lib/bdb.py
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¶
file
中Breakpoint
的行号。
- 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 版本加入。
- 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
。
派生类和客户端可以调用以下方法来操作断点。如果出现问题,这些方法返回包含错误消息的字符串;如果一切正常,则返回
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*。
- runcall(func, /, *args, **kwds)¶
调试单个函数调用,并返回其结果。
最后,该模块定义了以下函数:
- bdb.checkfuncname(b, frame)¶
根据
Breakpoint
*b* 的设置方式,返回是否应该在此处中断。如果它是通过行号设置的,它会检查
b.line
是否与 *frame* 中的行号相同。如果断点是通过函数名
设置的,我们必须检查我们是否在正确的 *frame*(正确的函数)中,以及我们是否在其第一个可执行行上。