python - Python 中经过评估/动态生成的函数的源代码

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

我正在寻找一种在运行时从包含源代码的字符串创建 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返回类似 '<ipython-input-19-8efed6025c6f>' 的内容对于这些类型的函数,这当然不是真正的文件。有没有办法在非交互式环境中做类似的事情?

最佳答案

所以我能够通过深入研究 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 的评论,了解如何在内置解释器中使用回溯打印。

关于python - Python 中经过评估/动态生成的函数的源代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50822656/

相关文章:

python - 如何从文档字符串生成html文档

python - 开箱即用的示例不适用于 python 3.3 预期字节 str 找到

javascript - WordPress 被黑客入侵以包含反向链接

javascript - 执行外部 Javascript NodeJS

python - Pandas : "Lost connection to MySQL server" "system error: 32 Broken pipe"

python - 导入错误 : No module named bz2 for Python 2. 7.2

python-3.x - 在 Python 3 中使用集合模块

javascript - 避免使用 eval() 动态构建事件处理程序

python - Windows python 上的 Utf-8

windows - 使用 pywin32 库中的 win32evtlog 写入 Windows 事件日志