【发布时间】:2020-07-17 20:42:31
【问题描述】:
在 Python 中,使用isinstance(obj, types.ModuleType) 很容易检查对象是否为模块。我们还可以以编程方式生成模块。然而,我有兴趣反过来 - 生成将创建导入导致模块被添加到 globals/locals 命名空间的代码。基本上是这样的函数assemble_import:
def assemble_import(module: types.ModuleType, name: str) -> str:
pass
大致满足以下条件:
import statistics
assert assemble_import(statistics, 'statistics') = 'import statistics'
from os import path
assert assemble_import(path, 'path') = 'from os import path'
import collections.abc
abc = collections.abc
assert assemble_import(abc, 'abc') = 'from collections import abc'
import abc as xyz
assert assemble_import(xyz, 'xyz') = 'import abc as xyz'
我不希望它使用抽象语法树,而是使用模块对象本身。到目前为止我所尝试的:
-
module.__spec__- 它返回带有 name 属性的ModuleSpec -
module.__package__- 不知道为什么,但大部分时间都是空的 -
module.__loader__- 通常是SourceFileLoader,也有name属性
name 属性的问题在于它是os.path 的“posixpath”,而from os import posixpath 显然不起作用。另外,我没有看到如何获取父模块(os.path 示例中的os)。
是否可以在 Python 中实现可行的(尽管不一定是生产就绪/防弹的)解决方案?换句话说,重新创建导入代码所需的包结构信息是否保留/可访问?
【问题讨论】:
-
听起来像是 XY 问题。你试图通过这种方式实现的实际目标是什么?你知道docs.python.org/3/library/importlib.html吗?
-
谢谢。是的,我知道。我不想操作我的自定义模块,但是任何用户提供的模块,我很好奇是否可以使用 Python 实现从对象生成代码。
-
我还不明白:在
assert assemble_import(xyz, 'xyz') = 'import abc as xyz'中,abc应该从哪里输出? -
来自模块对象。
xyz别名为abc(import abc as xyz)。 -
os.path在模块通常不应该有的方式上是独一无二的和特殊的——如果它不是 Python 的早期部分,它可能不会这样设计。如果您真的想将其视为os.path而不是posixpath或ntpath,则最好的选择是特殊情况。
标签: python python-3.x python-import code-generation