关于python:为什么使用-PyCharm-调试没有按预期进入断点

9次阅读

共计 1426 个字符,预计需要花费 4 分钟才能阅读完成。

前言

最近调试一段简单代码的时候遇到一个问题,我在某处打了断点,并认为依照预期应该会运行到指定的断点,但遗憾的是并没有。几经排查,发现了一处暗藏的“坑”。

用简略的代码复现

简略起见,用上面这段代码来复现遇到的问题:

class Person(object):

    def __init__(self, id):
        self.id = id
        self._person = None
        self._name = None

    @property
    def name(self):
        if self._person is None:
            self._person = db_get_person(self.id)
        return self._person['name']

    def __repr__(self):
        return '<Person: {}>'.format(self.name)

def db_get_person(id):
    return {'name': 'Jack'}

if __name__ == '__main__':
    p = Person('Jack')
    print(p.name)

这段代码定义了一个 Person 类型,构造函数接管 id 参数。它有一个 name 属性,在首次拜访时会调用 db_get_person()(示例就间接返回了)函数从数据库依据 id 加载这个人的信息,并将之缓存,后续再拜访时就返回缓存值。另外,还定义了 __repr__ 魔法办法,为了在打印 Person 对象时可能更加敌对。

让咱们在第 1824 行打上断点并开始调试,首先会运行到第 24 行。当点击持续运行下一个断点时,会发现程序间接运行完结了,而没有如预期进行。

为什么 PyCharm 没有运行到指定断点?


认真看下运行到第 24 行的调试界面,在 Variables 面板中会主动显示出以后作用域的所有变量。其中就有变量 p,而它显示为了 <Person: Jack>,这阐明此时 PyCharm 曾经主动运行了 Person.__repr__,而此魔法办法调用了 self.name。当运行第 24 行的 p.name 时,已不是首次运行。

看到这里就水落石出了,PyCharm 的 Variables 面板中的变量会被主动运行 Person.__repr__。在此阶段中,该办法波及到的逻辑如果有断点是不会被暂停的,换句话说也就不会运行到指定的断点。

PyCharm 调试界面中除了 Variables 面板能够查看变量外,Watches 面板也可能执行任意表达式来察看。如果应用不慎,也可能遇到雷同问题。比方:断点运行到第 24 行时,在 Watches 面板中增加变量 p.name

该如何解决?

既然明确了起因,那解决的思路就是不让 PyCharm 主动运行到特定的代码。

办法一:勾销第 24 行断点

因为勾销了第 24 行断点,调试逻辑不会在第 24 行停留,那么 Variables 面板就不会显示变量 p,也就不会调用 Person.__repr__。在运行第 24 行的 p.name 时就是首次运行,天然就能运行到第 18 行断点。

办法二:长期正文掉 Person.repr

因为正文了 Person.__repr__,调试停留在第 24 行时,只管 Variables 面板显示了变量 p,并不会通过 Person.__repr__ 调用 p.name。这样,也可能确保运行第 24 行的 p.name 是首次运行,天然就能运行到第 18 行断点。

总结

应用 PyCharm 调试具备缓存逻辑的代码时,要留神 VariablesWatches 面板中的变量是否已被主动执行对应的逻辑,从而导致没有进入到预期的断点。

正文完
 0