获得python函数的源代码是错误的

时间:2017-03-28 07:51:05

标签: python inspect dill

我想获取Python函数的源代码。但是,我正在处理的函数具有使用函数本身实例化的装饰器。似乎inspectdill有问题。特别是,我尝试了以下MWE:

class Decorator(object):
    def __init__(self, item):
        self.item = item
        self.func = None
    def __call__(self, func):
        self.func = func
        return self

@Decorator(42)
def fun_1():
    pass

@Decorator(lambda x: 42)
def fun_2():
    pass

@Decorator(fun_2.item)
def fun_3():
    pass

import inspect
print("Inspect results")
print(inspect.getsource(fun_1.func))
print(inspect.getsource(fun_2.func))
print(inspect.getsource(fun_3.func))

import dill
print("Dill results")
print(dill.source.getsource(fun_1.func))
print(dill.source.getsource(fun_2.func))
print(dill.source.getsource(fun_3.func))

对于函数fun_1fun_3,这会给出预期的结果。对于fun_2(尽管它与fun_3基本相同),inspectdill返回的源代码是错误的 - 它只给我装饰线。我希望得到

@Decorator(lambda x: 42)
def fun_2():
    pass

但我得到的只是

@Decorator(lambda x: 42)

我可以想象两个模块只搜索第一个函数声明。这个假设是否正确,除了重新实现inspectdill之外还有一个好的解决方法吗?

编辑:我使用的是Python 2.7,但使用Python 3.4时遇到了相同的行为。

1 个答案:

答案 0 :(得分:2)

我是dill作者。我认为你在inspect中发现了一个错误,关于在装饰器中解析包含lambda作为参数的代码块。

>>> f = lambda x: 42
>>> @Decorator(f)
... def fun_4():
...     pass
... 
>>> 
>>> print dill.source.getsource(fun_4.func)
@Decorator(f)
def fun_4():
    pass

>>>

请注意,只需使用指向lambda对象的指针即可。这就是你的解决方法。

我认为这个角落案例是inspect中的一个错误,dill正在使用它...所以这也是dill中的错误。

我已在dill GitHub页面上打开了一张票,我将进一步调查以查看(1)是否有可在dill中实施的简单解决方法,以及(2) )如果它确实是inspect中的一个错误(我猜它是) - 如果是这样的话,它应该填充给python开发人员。这是该票证的链接:https://github.com/uqfoundation/dill/issues/221