我正在尝试编写一个函数调试装饰器,它将会看到:
def foo(baz):
bar = 1
bar = 2
return bar
并将其包装到:
def foo(baz):
bar = 1
print 'bar: {}'.format(bar)
bar = 2
print 'bar: {}'.format(bar)
return bar
我需要将该功能作为文本播放,以获取“\ w +(?= \ s * [=])”,但不知道如何访问它。我有一个装饰我从一个有效的博客修改,但我只是尝试将其更改为:
class decorator_string_check(object):
def __init__(self, func):
self.func = func
wraps(func)(self)
def __call__(self, *args, **kwargs):
print dir(self.func)
print dir(self.func.__code__)
print self.func.__code__.__str__()
ret = self.func(*args, **kwargs)
return ret
@decorator_string_check
def fake(x):
y = 6
y = x
return y
y = fake(9)
并且我的价值很高,即:
['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']
['__class__', '__cmp__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'co_argcount', 'co_cellvars', 'co_code', 'co_consts', 'co_filename', 'co_firstlineno', 'co_flags', 'co_freevars', 'co_lnotab', 'co_name', 'co_names', 'co_nlocals', 'co_stacksize', 'co_varnames']
<code object fake at 0x7f98b8b1d030, file "./logging.py", line 48>
如何使用实际的“func”文本,在其上运行正则表达式并在装饰器类对象中查找我需要的东西?谢谢
答案 0 :(得分:6)
首先,我建议你做不做类似的事情。很难获得正常工作的代码,并且很难制作出正确的版本。
此外,我不知道你想要做什么。该装饰器是否应该在每次分配后添加print
语句并显示更新后的值?或者只跟踪给定的变量子集?
这就是说,要获取某些内容的源代码,您可以使用inspect
模块,特别是getsource
函数:
In [1]: def test():
...: a = 1
...: b = 2
...:
In [2]: import inspect
In [3]: inspect.getsource(test)
Out[3]: 'def test():\n a = 1\n b = 2\n'
In [4]: print(inspect.getsource(test))
def test():
a = 1
b = 2
您可以根据需要修改和检查源代码,最后compile()
新的源代码。
但请注意:
inspect
模块有一些函数可以让你获得调用decorator的堆栈框架,你可以从那里获取环境。阅读有关如何处理堆栈的here。getsource
只会引发OSError
。更“理智”的解决方案是不查看源代码,而是字节码。您可以使用dis
模块执行此操作。您可以尝试查看变量值何时更改并插入一些将打印该变量的字节码。
请注意,dis
模块在python3.4 +中得到了极大的增强,因此对于以前版本的python,这可能很难。
在尝试之前,您应该阅读Python bytecode hacks, gotos revisited之类的文章。它们让您了解如何查看字节码并使用它。
这可能更安全(例如,即使机器上不存在源文件仍然可以访问字节码),但我仍然认为你的想法是不一件好事除了练习外,还要做。
正如jsbueno所指出的那样,正确的方法(即python调试器)是使用sys.settrace
。
此功能允许您设置将为执行的每个“代码”调用的跟踪功能。该函数将知道何时调用函数,输入新块等。它允许您访问将执行代码的帧,因此您应该能够找到您感兴趣的值。
您应该检查lnotab_notes.txt
文件,以了解如何将作为此函数参数提供的数据映射到源代码位置,以了解何时执行赋值。
当我有时间(可能是下周结束)时,我会尝试基于这种方法来实现它。