【问题标题】:Source code for an eval'ed/dynamically generated function in PythonPython中评估/动态生成函数的源代码
【发布时间】:2018-11-22 04:12:33
【问题描述】:

我正在寻找一种在运行时从包含源代码的字符串创建 Python 函数的方法,这样可以通过检查获得源代码。

我目前的方法是这样的:

src = 'def foo(x, y):' + '\n\t' + 'return x / y'
g = {numpy: numpy, ...}  # Modules and such required for function
l = {}
exec(src, g, l)
func = l['foo']

效果很好,但该函数没有与之关联的源代码/文件。这使得调试变得困难(注意 foo() 中发生错误的行没有显示):

>>> foo(1, 0)
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-85-9df128c5d862> in <module>()
----> 1 myfunc(3, 0)

<string> in foo(x, y)

ZeroDivisionError: division by zero

如果我在 IPython 解释器中定义了一个函数,我可以使用 inspect.getsource 获取源代码,并将在回溯中打印出来。 inspect.getsourcefile 为这些类型的函数返回类似于 '&lt;ipython-input-19-8efed6025c6f&gt;' 的内容,这当然不是真正的文件。有没有办法在非交互环境中做类似的事情?

【问题讨论】:

  • inspect.getsource 不适用于标准交互式会话中定义的函数。如果在您尝试时它似乎可以工作,那么您可能一直在运行 IPython 而没有意识到。
  • 你不应该使用compile 吗? .用 compile 你可以先存储编译好的代码,然后在需要的时候执行。其中 exec 和 eval 在不返回对象的情况下进行评估
  • @user2357112 你说得对,我是在 IPython 中完成的,并错误地认为它也适用于标准交互式解释器。

标签: python python-3.x eval code-generation


【解决方案1】:

所以我能够通过深入研究 IPython 源代码部分弄清楚这一点。它利用了内置模块linecache,其中包含从文件中读取源代码并缓存结果的函数。 inspecttraceback 模块都使用这个模块来获取函数的源代码。

解决方案是用与问题中相同的方式创建函数,但使用 compile 和一个虚构的唯一文件名:

source = 'def foo(x, y):' + '\n\t' + 'return x / y'

filename = '<dynamic-123456>'  # Angle brackets may be required?
code = compile(source, filename, 'exec')

g = {numpy: numpy, ...}  # Modules and such required for function
l = {}
exec(src, g, l)
func = l['foo']

linecache 包含一个变量cache,它是将文件名映射到(size, mtime, lines, fullname) 元组的字典。您可以简单地为假文件名添加一个条目:

lines = [line + '\n' for line in source.splitlines()]

import linecache
linecache.cache[filename] = (len(source), None, lines, filename)

然后,该函数将使用 inspect.getsource()、IPython 的 ?/?? 语法和 IPython 回溯。但是,它似乎仍然无法在内置回溯中工作。这对我来说已经足够了,因为我几乎总是在 IPython 中工作。

编辑:请参阅下面的 user2357112 的评论,了解如何在内置解释器中使用回溯打印。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2017-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-05
  • 2011-07-29
相关资源
最近更新 更多