破解 python 的导入语句
Hacking python's import statement
我正在构建一个 Python 模块用于一个相当具体的目的。我想用它做的是从中获得更多 import
ing 东西的功能。
我想要一个设置,通过说 from my_module import foo
将 运行 一个函数并传递字符串 "foo"
。此函数将 return 应导入的对象。
比如我想做一个基于云的导入系统。我想将社区脚本存储在云中,然后在用户尝试导入它们时下载它们。
也许我使用代码 from cloud import test_module
。这将检查缓存以确定 test_module
是否已下载。如果是这样,它将 return 该模块。如果没有,它将在导入之前下载模块。
我怎样才能在 Python 中完成这样的事情,通过它可以从云端无缝地 import
编辑动态范围的子模块?
对您所要求的内容的全功能支持可能需要使用 importlib
和挂钩到导入机制的各个部分的一堆复杂代码。但是,可以仅使用一个伪装成模块的自定义 class 来实现更有限的解决方案。
导入模块时,Python 首先检查 sys.modules
字典以查看模块是否是键。如果是这样,它 returns 与键关联的值。无论值是什么,它都会执行此操作,因此您可以将任何类型的对象放入 sys.modules
并且 Python 会将其视为一个模块。一个模块的代码甚至可以替换它自己在 sys.modules
中的条目,并且即使是第一次 import
ed!
也会使用替换项
因此,要实现按需下载其他模块的奇特模块,请将模块本身替换为自定义 class 的实例,然后编写 class a __getattr__
或__getattribute__
完成您想要的工作的方法。
这是一个简单的示例模块,return它是您在其中查找的任何属性的字符串。该字符串将始终与请求的属性名称相同。在您的代码中,您可能想要进行花哨的网络缓存查找和下载,然后 return 获取的模块对象,而不只是 return 一个字符串。
class FakeModule(object):
def __getattribute__(self, name):
return name
import sys
sys.modules[__name__] = FakeModule()
在我的系统中,我将其保存为 fakemodule.py
。现在,如果我执行 from fakemodule import foo
,我会在我的本地命名空间中得到 foo
和值 'foo'
。
请注意,这仅适用于一级深度导入。如果你这样做 from fakemodule.subpackage import name
它将不起作用,因为 sys.modules
中没有 fakemodule.subpackage
条目。
我正在构建一个 Python 模块用于一个相当具体的目的。我想用它做的是从中获得更多 import
ing 东西的功能。
我想要一个设置,通过说 from my_module import foo
将 运行 一个函数并传递字符串 "foo"
。此函数将 return 应导入的对象。
比如我想做一个基于云的导入系统。我想将社区脚本存储在云中,然后在用户尝试导入它们时下载它们。
也许我使用代码 from cloud import test_module
。这将检查缓存以确定 test_module
是否已下载。如果是这样,它将 return 该模块。如果没有,它将在导入之前下载模块。
我怎样才能在 Python 中完成这样的事情,通过它可以从云端无缝地 import
编辑动态范围的子模块?
对您所要求的内容的全功能支持可能需要使用 importlib
和挂钩到导入机制的各个部分的一堆复杂代码。但是,可以仅使用一个伪装成模块的自定义 class 来实现更有限的解决方案。
导入模块时,Python 首先检查 sys.modules
字典以查看模块是否是键。如果是这样,它 returns 与键关联的值。无论值是什么,它都会执行此操作,因此您可以将任何类型的对象放入 sys.modules
并且 Python 会将其视为一个模块。一个模块的代码甚至可以替换它自己在 sys.modules
中的条目,并且即使是第一次 import
ed!
因此,要实现按需下载其他模块的奇特模块,请将模块本身替换为自定义 class 的实例,然后编写 class a __getattr__
或__getattribute__
完成您想要的工作的方法。
这是一个简单的示例模块,return它是您在其中查找的任何属性的字符串。该字符串将始终与请求的属性名称相同。在您的代码中,您可能想要进行花哨的网络缓存查找和下载,然后 return 获取的模块对象,而不只是 return 一个字符串。
class FakeModule(object):
def __getattribute__(self, name):
return name
import sys
sys.modules[__name__] = FakeModule()
在我的系统中,我将其保存为 fakemodule.py
。现在,如果我执行 from fakemodule import foo
,我会在我的本地命名空间中得到 foo
和值 'foo'
。
请注意,这仅适用于一级深度导入。如果你这样做 from fakemodule.subpackage import name
它将不起作用,因为 sys.modules
中没有 fakemodule.subpackage
条目。