如何在源代码中设置pdb断点条件?
问题:如果我有一个复杂的断点条件,我不想每次重新启动程序时都要先用 pdb.set_trace()
然后手动粘贴断点命令。
有没有办法在我的源代码中直接设置断点?
我尝试过的:我查看了文档,尝试插入这一行:
pdb.run('break 445, a == 1')
但是当执行到那一行时,我遇到了这个错误:
pdb.run('break 445, a == 1')
File "C:\Python25\lib\pdb.py", line 1123, in run
Pdb().run(statement, globals, locals)
File "C:\Python25\lib\bdb.py", line 366, in run
exec cmd in globals, locals
File "<string>", line 1
break 445, a == 1
^
SyntaxError: invalid syntax
1 个回答
4
pdb
不能直接做到这一点。不过,你可以在自己的程序里用几种方法自己实现。
第一种方法就是用一个全局变量来控制断点的进入。像下面这个简单的例子就很容易理解:
_breakpoints = {}
def reset_breakpoints(disabled=[]):
global _breakpoints
_breakpoints = dict((x, False) for x in disabled)
def set_breakpoint(tag, condition=True):
if tag not in _breakpoints:
_breakpoints[tag] = True
if condition:
pdb.set_trace()
else:
if _breakpoints[tag] and condition:
pdb.set_trace()
def mycode():
some_command()
set_breakpoint('mycode0')
another_command()
set_breakpoint('mycode1', x == 4)
第一次运行时,你的字典里没有这个值,所以你会把它加进去并暂停程序。但之后,你可以修改字典里的值,然后在真正暂停之前先检查一下是否需要暂停。你也可以用 eval
等更复杂的条件来判断,但其实像上面那样做会简单很多。这种方法比较轻便,让你完全掌控程序何时停止。唯一需要注意的是,当你重新开始调试会话时,如果你把某个值设置为 False
,你得记得自己初始化字典(通常是清空它)。虽然这不和调试器整合在一起,但也不会消耗太多资源。
还有一点要记住……在你进入调试器之前,你是无法控制它的。这意味着,除非你一开始就执行 pdb.run()
,否则你实际上并不在调试器里,而在我所知道的情况下,没有暂停程序就无法进入调试器。不过,一旦你进入了调试器,就可以通过一些巧妙的方法使用调用栈来获取 pdb
对象。这是在 IPython 中的,遗憾的是,实际的调用栈深度可能会因为你使用的 pdb
版本不同而有所不同,但你可以尝试下面的代码来获取当前运行的 Pdb 对象的引用。一旦你得到了它,就可以直接用它的接口进行交互。下面是一个例子:
In [331]: %debug pass
NOTE: Enter 'c' at the ipdb> prompt to continue execution.
None
> <string>(1)<module>()
ipdb> import inspect
ipdb> f = inspect.stack()[6]
ipdb> f0 = f[0]
ipdb> myipdb = f0.f_locals['self']
ipdb> myipdb.
myipdb.aliases myipdb.dispatch_exception myipdb.do_next myipdb.fncache myipdb.help_help myipdb.lastcmd myipdb.runctx
myipdb.botframe myipdb.dispatch_line myipdb.do_p myipdb.forget myipdb.help_ignore myipdb.lineinfo myipdb.runeval
myipdb.bp_commands myipdb.dispatch_return myipdb.do_pdef myipdb.format_stack_entry myipdb.help_j myipdb.lineno myipdb.set_break
myipdb.break_anywhere myipdb.displayhook myipdb.do_pdoc myipdb.get_all_breaks myipdb.help_jump myipdb.list_command_pydb myipdb.set_colors
myipdb.break_here myipdb.do_EOF myipdb.do_pfile myipdb.get_break myipdb.help_l myipdb.lookupmodule myipdb.set_continue
myipdb.breaks myipdb.do_a myipdb.do_pinfo myipdb.get_breaks myipdb.help_list myipdb.mainpyfile myipdb.set_next
myipdb.canonic myipdb.do_alias myipdb.do_pinfo2 myipdb.get_file_breaks myipdb.help_n myipdb.misc_header myipdb.set_quit
myipdb.checkline myipdb.do_args myipdb.do_pp myipdb.get_names myipdb.help_next myipdb.new_do_down myipdb.set_return
myipdb.clear_all_breaks myipdb.do_b myipdb.do_psource myipdb.get_stack myipdb.help_p myipdb.new_do_frame myipdb.set_step
myipdb.clear_all_file_breaks myipdb.do_break myipdb.do_q myipdb.handle_command_def myipdb.help_pdb myipdb.new_do_quit myipdb.set_trace
myipdb.clear_bpbynumber myipdb.do_bt myipdb.do_quit myipdb.help_EOF myipdb.help_pp myipdb.new_do_restart myipdb.set_until
myipdb.clear_break myipdb.do_c myipdb.do_r myipdb.help_a myipdb.help_q myipdb.new_do_up myipdb.setup
myipdb.cmdloop myipdb.do_cl myipdb.do_restart myipdb.help_alias myipdb.help_quit myipdb.nohelp myipdb.shell
myipdb.cmdqueue myipdb.do_clear myipdb.do_return myipdb.help_args myipdb.help_r myipdb.onecmd myipdb.stack
myipdb.color_scheme_table myipdb.do_commands myipdb.do_retval myipdb.help_b myipdb.help_restart myipdb.parseline myipdb.stdin
myipdb.columnize myipdb.do_condition myipdb.do_run myipdb.help_break myipdb.help_return myipdb.parser myipdb.stdout
myipdb.commands myipdb.do_cont myipdb.do_rv myipdb.help_bt myipdb.help_run myipdb.postcmd myipdb.stop_here
myipdb.commands_bnum myipdb.do_continue myipdb.do_s myipdb.help_c myipdb.help_s myipdb.postloop myipdb.stopframe
myipdb.commands_defining myipdb.do_d myipdb.do_step myipdb.help_cl myipdb.help_step myipdb.precmd myipdb.stoplineno
myipdb.commands_doprompt myipdb.do_debug myipdb.do_tbreak myipdb.help_clear myipdb.help_tbreak myipdb.preloop myipdb.trace_dispatch
myipdb.commands_resuming myipdb.do_disable myipdb.do_u myipdb.help_commands myipdb.help_u myipdb.print_list_lines myipdb.undoc_header
myipdb.commands_silent myipdb.do_down myipdb.do_unalias myipdb.help_condition myipdb.help_unalias myipdb.print_stack_entry myipdb.use_rawinput
myipdb.complete myipdb.do_enable myipdb.do_unt myipdb.help_cont myipdb.help_unt myipdb.print_stack_trace myipdb.user_call
myipdb.complete_help myipdb.do_exit myipdb.do_until myipdb.help_continue myipdb.help_until myipdb.print_topics myipdb.user_exception
myipdb.completedefault myipdb.do_h myipdb.do_up myipdb.help_d myipdb.help_up myipdb.prompt myipdb.user_line
myipdb.completekey myipdb.do_help myipdb.do_w myipdb.help_debug myipdb.help_w myipdb.quitting myipdb.user_return
myipdb.completenames myipdb.do_ignore myipdb.do_whatis myipdb.help_disable myipdb.help_whatis myipdb.rcLines
myipdb.curframe myipdb.do_j myipdb.do_where myipdb.help_down myipdb.help_where myipdb.reset
myipdb.curindex myipdb.do_jump myipdb.doc_header myipdb.help_enable myipdb.identchars myipdb.returnframe
myipdb.default myipdb.do_l myipdb.doc_leader myipdb.help_exec myipdb.interaction myipdb.ruler
myipdb.defaultFile myipdb.do_list myipdb.emptyline myipdb.help_exit myipdb.intro myipdb.run
myipdb.dispatch_call myipdb.do_n myipdb.execRcLines myipdb.help_h myipdb.is_pydb myipdb.runcall
ipdb> myipdb.