gpt4 book ai didi

python - 在装饰器中将 python 函数解析为字符串

转载 作者:行者123 更新时间:2023-11-28 21:14:56 25 4
gpt4 key购买 nike

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

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)

我没有得到任何有值(value)的东西,即:

['__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”文本,在其上运行正则表达式并在装饰器类对象中找到我需要的东西?谢谢

最佳答案

首先,我建议您不要做那样的事情。很难获得工作代码,也很难制作正确的版本。

此外,我真的不知道你到底想做什么。这个装饰器是否应该在每次分配后添加一个 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 模块具有一些功能,可让您获取调用装饰器的堆栈框架,并从那里获取环境。阅读here关于如何处理堆栈。
  • 源代码可能不可用。代码可以编译成字节码,原始文件可以删除。在这种情况下,getsource 只会引发一个 OSError

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

请注意 dis 模块在 python3.4+ 中得到了极大的增强,因此对于以前的 python 版本,这可能很难。

您可能应该阅读类似 Python bytecode hacks, gotos revisited 的文章在尝试这个之前。它们让您了解如何查看字节码并使用它。

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


正如 jsbueno 指出的做你想做的事情的正确方法(即 python 调试器)是使用 sys.settrace .

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

你应该检查 lnotab_notes.txt文件以了解作为此函数的参数提供的数据如何映射到源代码位置以了解何时执行分配。

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

关于python - 在装饰器中将 python 函数解析为字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30944349/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com