5

对于一些快速的 Python 调试,我偶尔import pdb;pdb.set_trace()会插入一行代码,让我进入调试器。非常便利。但是,如果我想调试一个循环,它可能会运行很多很多次,它会在某种程度上失去它的有效性。我可以继续混搭c很多很多次,但是有没有办法删除/忽略那个硬编码的断点,这样我就可以让它完成?

我可以设置一个全局标志并有条件地运行它,但是我会失去单行断点的“独立性”,也需要为每个pdb.set_trace().

4

5 回答 5

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()

笔记:

  1. 我个人更ipdb喜欢pdb

  2. 使用时pdb,由于实际调用的函数pdb.set_trace在包装器中,因此中断时的当前帧将在其中。该up命令为您提供所需的框架。ipdb如果使用(包装器中的实现确保在正确的位置中断),则不会发生这种情况。

  3. 使用时ipdb,我发现它报告调用者帧行号不一致。这意味着你第一次这样做pdb.set_trace.disable_current(),它可能不成立。如果下一次它坏了,就再做一次——第二次成立。

  4. 一般来说,拥有自己的pdb包装器对其他事情也很有用。我有自己的set_trace包装器,可以避免中断 if not sys.stdout.isatty(如果进程未连接到终端,也不会在将 stdout 重定向到文件/管道时中断)。也就是说,拥有自己的pdb包装器并调用它set_trace而不是pdb's 是一种很好的做法。

于 2013-04-05T21:12:50.653 回答
1

以下 hack 将禁用当前运行中的所有其他调用set_trace(即,从代码中的任何位置)。

创建这个noop_pdb插件:

# 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,拿起插件。

编辑:另一种实现这种不需要的hack的方法noop_pdb是用noop替换set_trace,而不是整个pdb模块:pdb.set_trace = lambda: None

于 2013-04-05T20:04:12.683 回答
0

您是否尝试过使用 pdb 提供的“直到”命令?

http://docs.python.org/2/library/pdb.html#debugger-commands

直到)

继续执行,直到到达行号大于当前行的行或从当前帧返回。

于 2014-01-06T02:51:35.410 回答
0

你看了condition bpnumber吗?您可以禁用断点,然后使其成为有条件的。或者,您可以首先使用breaktbreak使断点成为条件断点。详细信息可以在这里找到。

于 2013-04-05T18:47:15.173 回答
0

在 pdb 中使用 'return' 可以在循环中传递 pdb.set_trace() 并跳转到当前函数的最后一行。

于 2015-05-11T16:54:52.147 回答