如何使装饰器对调试器透明

时间:2018-09-07 15:40:24

标签: python debugging decorator pudb

我正在一个修饰器库上工作,该修饰器库正在修改函数的关键字参数,并且该库正在执行我想要的操作,但是在调试时,每当调用用户函数时,调试器必须传递装饰器库代码。

我将装饰器实现为一个类(请参见https://github.com/mapa17/configfy/blob/master/configfy/decorator.py

,用户函数由以下库代码包装:

def __call__(self, *args, **kwargs):
    if self.needs_wrapping:
        self.needs_wrapping = False
        self.func = args[0]
        functools.update_wrapper(self, self.func)
        self.kwargs = self.__get_kw_args(self.func)

        # If config file is specified in decorator, new kwargs can be precalculated!
        if self.config is not None:
            self.new_kwargs = self._get_new_kwargs()

        return self

    # Use precalculated kwargs if available
    if self.new_kwargs is None:
        new_kwargs = self._get_new_kwargs()
    else:
        new_kwargs = self.new_kwargs

    # Overwrite them with any passed arguments; passed arguments have priority!
    new_kwargs.update(kwargs)

    # Call target (aka user) function with altered kwargs
    return self.func(*args, **new_kwargs)

那么调试时是否有可能跳过该库代码?

2 个答案:

答案 0 :(得分:1)

装饰器没有什么神奇的。 @decorator语法只是语法糖,因此在您编写时:

@decorate
def some_func(...):
   # ...

从技术上讲,真正发生的事情是:

def some_func(...):
   # ...

some_func = decorate(some_func)

IOW,不,没有办法“使装饰器对调试器透明”,因为“装饰器”只是一个普通的可调用对象(通常但不一定)返回另一个普通的可调用对象-实际上,没有“装饰器”之类的东西,可调用对象就是装饰器(如果您这样使用的话),仅此而已。

答案 1 :(得分:1)

正如@ bruno-desthuilliers所提到的,装饰器是用户功能的包装,无法以某种方式删除它。

可以做的是,使用 skip 选项see

使调试器跳过装饰器模块代码。

由于我有兴趣使用pudb进行调试,因此我创建了一个pull请求,为pdb see启用了类似功能

对于pdb

import pdb
from configfy import configfy as cfy    

@cfy
def fuu(kw_me=42):
    print(kw_me)

if __name__ == '__main__':
    pdb.Pdb(skip=['configfy.*']).set_trace()
    fuu()

对于pudb(如果接受了拉取请求)

import pudb
from configfy import configfy as cfy

# Prevent pudb from stepping into the decorator library code
pudb._get_debugger(skip=['configfy.*'])


@cfy
def fuu(kw_me=42):
    print(kw_me)

if __name__ == '__main__':
    pudb.set_trace()
    fuu()