2

我正在研究一个正在修改函数的关键字参数的装饰器库,并且该库正在做我想要它做的事情,但是在调试时,每当调用用户函数时,调试器都必须通过装饰器库代码。

我将装饰器实现为一个类(参见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)

那么在调试时是否有可能以某种方式跳过这个库代码?

4

2 回答 2

1

正如@bruno-desthuilliers 所提到的,装饰器是用户函数的包装器,没有办法以某种方式将其删除。

可以做的是,让调试器跳过装饰器模块代码,使用跳过选项

由于我对使用 pudb 进行调试很感兴趣,因此我创建了一个拉取请求,为 pdb 启用了类似的功能,请参阅

对于 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()
于 2018-09-12T12:27:12.973 回答
1

装饰器没有什么神奇的。@decorator语法只是语法糖,所以当你写:

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

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

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

some_func = decorate(some_func)

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

于 2018-09-11T12:19:53.117 回答