对于一些快速的Python调试,我偶尔会抛出import pdb;pdb.set_trace()
行,这会让我进入调试器。非常便利。但是,如果我想调试一个可能运行很多次的循环,它会在一定程度上失去它的效果。我可以在c
上混合许多次,但很多次,但有没有办法删除/忽略那个硬编码的断点,这样我就可以让它完成?
我可以设置一个全局标志并有条件地运行它,但之后我会丢失单行断点的'standalone-ness',同时还需要每个pdb.set_trace()
的另一个标志。
答案 0 :(得分:2)
我的另一个答案是快速破解,并不完美(将禁用所有对set_trace
的调用)。这是一个更好的解决方案。
我们定义一个包裹pdb
的模块。其中,set_trace
是一个可调用对象,维护一个被禁用的调用者列表(由文件名/行号标识)。
# mypdb.py
import inspect
import sys
try:
import ipdb as PDB
except ImportError:
import pdb as PDB
class SetTraceWrapper(object):
def __init__(self):
self.callers_disabled = set()
self.cur_caller = None
def __call__(self):
self.cur_caller = self.get_caller_id()
if self.cur_caller in self.callers_disabled:
# already disabled for caller
#print 'set_trace SKIPPED for %s' % ( self.cur_caller, )
return
#print 'set_trace BREAKING for %s' % ( self.cur_caller, )
try:
PDB.set_trace(sys._getframe().f_back)
except TypeError:
PDB.set_trace()
def disable_current(self):
#print 'set_trace DISABLING %s' % ( self.cur_caller, )
self.callers_disabled.add(self.cur_caller)
def get_caller_id(self, levels_up = 1):
f = inspect.stack()[levels_up + 1]
return ( f[1], f[2] ) # filename and line number
set_trace = SetTraceWrapper()
在您的代码中,请确保使用包装器:
import mypdb as pdb; pdb.set_trace()
如果要禁用当前set_trace
- 主叫行,请执行以下操作:
pdb.set_trace.disable_current()
注意:
我个人更喜欢ipdb
而不是pdb
使用pdb
时,由于实际调用pdb.set_trace
的函数位于包装器中,因此当前帧在断开时将在其中。 up
命令可以获得您想要的帧。如果使用ipdb
,则不会发生这种情况(包装器中的实现确保在正确的位置中断)。
使用ipdb
时,我发现它不一致地报告来电者帧号码。这意味着您第一次执行pdb.set_trace.disable_current()
时,可能无法执行此操作。如果它下次破裂,请再次执行 - 第二次暂停。
通常,拥有自己的pdb
包装器对其他事情也很有用。我有自己的set_trace
包装器,它可以避免中断not sys.stdout.isatty
(如果进程没有连接到终端,你也不想破坏,也不会将stdout重定向到文件/管道)。也就是说,拥有自己的pdb
包装并调用其set_trace
代替pdb
是一种很好的做法。
答案 1 :(得分:1)
以下黑客将在当前运行中禁用所有其他来电至set_trace
(例如,代码中的任何位置)。
创建此noop_pdb
drop-in:
# noop_pdb.py
def set_trace(*args, **kwargs):
pass
然后,一旦您的代码在真实的pdb.set_trace
中中断,并且您想要禁用对set_trace
的其余调用,请执行以下操作:
sys.modules['pdb'] = __import__('noop_pdb')
下次解释器会遇到如下行:
import pdb;pdb.set_trace()
它可以避免重新导入内置pdb
,从而获取内置功能。</ p>
编辑:实现此hack的另一种方法(不需要noop_pdb
)是将set_trace
替换为noop而不是整个pdb
模块:pdb.set_trace = lambda: None
< / p>
答案 2 :(得分:0)
你看过condition bpnumber
了吗?您可以禁用断点,然后使其成为条件。或者,您可以使用break
或tbreak
来使断点首先处于条件状态。可以找到详细信息here。
答案 3 :(得分:0)
您是否尝试过使用pdb提供的“until”命令?
来自http://docs.python.org/2/library/pdb.html#debugger-commands:
<强> UNT(IL)强>
继续执行,直到行号更大的行 到达当前帧或从当前帧返回时。