在decorator中将python函数解析为字符串

在decorator中将python函数解析为字符串,python,decorator,python-decorators,python-magic,Python,Decorator,Python Decorators,Python Magic,我正在尝试编写一个函数调试装饰器,它将关注: 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*[=])”,但不知道如何访问该函数。我从一个博客上修改了一个装饰器,但我只是尝

我正在尝试编写一个函数调试装饰器,它将关注:

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>
“UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU"名称","新","减少","减少","减少"前","报告","设置属性","大小","strunc代码“,”函数默认值“,”函数命令“,”函数文档“,”函数全局“,”函数名称“]
“UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUreduce_uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu“,”co_firstlineno“,”co_flags“,”co_freevars“,”co_lnotab“,”co_name“,”co_name“,”co_nlocals“,”co_stacksize“,”co_varnames“]
<0x7f98b8b1d030处的代码对象伪,文件“/logging.py”,第48行>

如何处理实际的“func”文本,在其上运行正则表达式,并在decorator类对象中找到所需的内容?谢谢你,首先,我建议你做而不是那样做。很难获得工作代码,也很难生成正确的版本

除此之外,我真的不知道你到底想做什么。这个修饰师应该在每次赋值后添加一个
打印
语句并显示更新后的值吗?还是只跟踪给定的变量子集

也就是说,要获得某个东西的源代码,您可以使用模块,尤其是函数:

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
您可以根据自己的意愿修改和检查源代码,最后修改和检查新的源代码

但请注意:

  • 修改源代码时必须小心,因为很容易创建语法无效的代码(想想:多行表达式等)
  • 编译时,您希望在与原始函数相同的范围内进行编译。
    inspect
    模块具有一些函数,允许您获取调用decorator的stackframe,并从中获取环境。请阅读有关如何处理堆栈的内容
  • 源代码可能不可用。代码可以用字节码编译,原始文件可能会被删除。在这种情况下,
    getsource
    只会引发一个
    OSError

一个更“合理”的解决方案是不看源代码,而是看字节码。您可以使用模块来执行此操作。您可以尝试查看变量的值何时更改,并插入一些字节码来打印该变量

请注意,
dis
模块在python3.4+中得到了极大的增强,因此在python的早期版本中,这可能很难实现

在尝试之前,您可能应该阅读类似的文章。它们让您了解如何看待字节码并使用它

这可能更安全(例如,即使源文件在机器上不存在,字节码仍然可以访问),但我仍然认为您心目中的不是一件好事,除非是作为练习


正如jsbueno指出的那样,做您想要做的事情(即python调试器)的正确方法是使用

此函数允许您设置跟踪函数,该函数将为执行的每个“代码”调用。该函数将知道何时调用函数、输入新块等。它允许您访问将执行代码的帧,因此您应该能够找到感兴趣的值

您应该检查该文件,以了解如何将作为此函数参数提供的数据映射到源代码位置,从而了解何时执行赋值


当我有时间(可能是下周末)时,我将尝试基于这种方法实现一些东西来演示它。

实际上是一个理智的解决方案(而不仅仅是“更理智的”)就是要使用python调试工具,使用sys.settrace
,并有效地编写一个自定义调试器,该调试器将比较每行后面的局部变量值,并打印不同的值。在修饰代码的持续时间内,应该不难找到一个适当地启用
settrace
的装饰器。@jsb上野:你是对的。我不知道这件事,而且这看起来确实是做类似事情的唯一正确方式。我已经把它添加到我的答案中。@Bakuriu doumo arigatou gozaimasu…anata wa watashi yori mo kashikoku miemasu:)我想跟踪所有/每个变量的赋值,只是想确切地知道在tim的那个时刻变量是什么e、 这样我就可以装饰一些不起作用的东西,而不是1238234打印语句方法。我相信全世界都可以使用我们的装饰器“这个装饰器应该在每次作业后添加一个打印语句并显示更新的值吗?”是的,这就是我要做的