s-m*_*m-e 7 python inspect python-3.x
我一直在使用inspectPython 标准库中的模块。
以下示例运行良好(假设inspect已导入):
def foo(x, y):
return x - y
print(inspect.getsource(foo))
Run Code Online (Sandbox Code Playgroud)
...将打印def foo(x, y):\n return x - y\n并...
bar = lambda x, y: x / y
print(inspect.getsource(bar))
Run Code Online (Sandbox Code Playgroud)
...将打印bar = lambda x, y: x / y\n。到目前为止,一切都很好。然而,在下面的例子中事情变得有点奇怪:
print(inspect.getsource(lambda x, y: x / y))
Run Code Online (Sandbox Code Playgroud)
...将打印print(inspect.getsource(lambda x, y: x / y))并...
baz = [2, 3, lambda x, y: x / y, 5]
print(inspect.getsource(baz[2]))
Run Code Online (Sandbox Code Playgroud)
...将打印baz = [2, 3, lambda x, y: x / y, 5]。
该模式似乎是所有相关的源代码行(无论上下文如何)都由getsource. 这些行中的其他所有内容(在我的例子中,除了所需的函数源/定义之外)也包括在内。是否有另一种“替代”方法,它允许提取代表函数源代码的内容 - 并且仅代表其源代码 - 最好以某种匿名方式?
编辑(1)
def foo(x, y):
return x - y
bar = [1, 2, foo, 4]
print(inspect.getsource(bar[2]))
Run Code Online (Sandbox Code Playgroud)
...将打印def foo(x, y):\n return x - y\n。
不幸的是,这是不可能的inspect,并且如果不再次解析(和编译)源代码就不可能工作。inspect的getsource方法相当有限:它使用getsourcelines调用 then findsource,这实际上会解开您的对象,直到我们最终得到 a PyCodeObject。
此时,我们正在处理已编译的字节码。原始来源留下的只是片段和提示,例如co_firstlineno:
Run Code Online (Sandbox Code Playgroud)/* Bytecode object */ typedef struct { /* ... other fields omitted ... */ int co_firstlineno; /* first source line number */ PyObject *co_code; /* instruction opcodes */ /* ... other fields omitted ... */ } PyCodeObject;
顺便说一句,与 类似PyCodeObject, aPyFrameObject也只包含一个f_lineno,但不包含列,这解释了为什么回溯仅包含文件名和行:该列不会编译到字节码中。
由于字节码不包含比(第一)行更具体的区域,因此不可能从inspect或任何其他仅使用(公共)字节码信息的库中获取确切的源位置,而无需进一步解析。这也适用于仅使用字节码的任何其他选项,例如pickle.
inspect使用公共信息 ( co_firstlineno),然后仅搜索函数的合适开始和周围块的结束。然而,inspect已经差不多了,但是它只找到任意一个块,而没有找到正确的块,而且目前还找不到正确的块。inspect标记整行并且不从正确的变体开始,它也不知道正确的相应源代码区域。
假设我们有
plus, minus, mult = lambda x: x + 1, lambda y: y - 1, lambda z: z * 5
Run Code Online (Sandbox Code Playgroud)
我们想要的只是minus。由于字节码不包含 a co_firstcolumn,因此我们只有完整的行可用。我们可以解析所有 lambda,但我们仍然不知道哪个 lambda 适合我们的co_code. 我们需要再次编译它们并检查它们的字节码是否适合原始字节码。
最后,我们必须这样做:再次解析源代码并找到正确的PyCodeObject. 如果我们至少有一个起始列号,那就容易多了,因为我们可以只使用语法分析,但 AST目前只保留行号。因此,要么inspect需要一个大补丁,要么字节码需要包含编译对象的起始列。
| 归档时间: |
|
| 查看次数: |
2067 次 |
| 最近记录: |