python 中的延迟加载模块
Lazy-loading modules in python
我正在尝试组装一个系统来处理不明确存在的模块的延迟加载。基本上我有一个带有许多端点的 http 服务器,我不知道我想以编程方式提供导入。这些模块都有一个统一的方法签名,只是它们不会提前存在。
import lazy.route as test
import lazy.fake as test2
test('Does this exist?') # This sends a post request.
test2("This doesn't exist.") # Also sends a post request
我可以使用统一的装饰器处理这些导入所需的所有逻辑,我只是找不到在 python 中导入 "decorating" 的任何方式,或者实际上无法在任何方式中与它们交互一种编程方式。
有人有这方面的经验吗?我一直在四处寻找,我发现的最接近的东西是 ast
模块,根据我目前的理解,这会导致我当前的一种非常糟糕的 hacky 实现(比如找到所有导入语句和手动覆盖导入函数)
不是在寻找讲义,只是要开始查看的 python 代码库的一部分,或者有人做过类似事情的示例。
我在 google 上有点聪明,设法找到了一个专门解决这个问题的 PEP,它恰好相对不为人知,可能是因为合理用途的子集非常狭窄。
我发现了一段优秀的示例代码,展示了新的 sys.meta_path
实现。我在下面 post 编辑了它以获取有关如何动态 bootstrap 您的导入语句的信息。
import sys
class VirtualModule(object):
def hello(self):
return 'Hello World!'
class CustomImporter(object):
virtual_name = 'my_virtual_module'
def find_module(self, fullname, path):
"""This method is called by Python if this class
is on sys.path. fullname is the fully-qualified
name of the module to look for, and path is either
__path__ (for submodules and subpackages) or None (for
a top-level module/package).
Note that this method will be called every time an import
statement is detected (or __import__ is called), before
Python's built-in package/module-finding code kicks in."""
if fullname == self.virtual_name:
# As per PEP #302 (which implemented the sys.meta_path protocol),
# if fullname is the name of a module/package that we want to
# report as found, then we need to return a loader object.
# In this simple example, that will just be self.
return self
# If we don't provide the requested module, return None, as per
# PEP #302.
return None
def load_module(self, fullname):
"""This method is called by Python if CustomImporter.find_module
does not return None. fullname is the fully-qualified name
of the module/package that was requested."""
if fullname != self.virtual_name:
# Raise ImportError as per PEP #302 if the requested module/package
# couldn't be loaded. This should never be reached in this
# simple example, but it's included here for completeness. :)
raise ImportError(fullname)
# PEP#302 says to return the module if the loader object (i.e,
# this class) successfully loaded the module.
# Note that a regular class works just fine as a module.
return VirtualModule()
if __name__ == '__main__':
# Add our import hook to sys.meta_path
sys.meta_path.append(CustomImporter())
# Let's use our import hook
import my_virtual_module
print my_virtual_module.hello()
完整博客 post 是 here
我正在尝试组装一个系统来处理不明确存在的模块的延迟加载。基本上我有一个带有许多端点的 http 服务器,我不知道我想以编程方式提供导入。这些模块都有一个统一的方法签名,只是它们不会提前存在。
import lazy.route as test
import lazy.fake as test2
test('Does this exist?') # This sends a post request.
test2("This doesn't exist.") # Also sends a post request
我可以使用统一的装饰器处理这些导入所需的所有逻辑,我只是找不到在 python 中导入 "decorating" 的任何方式,或者实际上无法在任何方式中与它们交互一种编程方式。
有人有这方面的经验吗?我一直在四处寻找,我发现的最接近的东西是 ast
模块,根据我目前的理解,这会导致我当前的一种非常糟糕的 hacky 实现(比如找到所有导入语句和手动覆盖导入函数)
不是在寻找讲义,只是要开始查看的 python 代码库的一部分,或者有人做过类似事情的示例。
我在 google 上有点聪明,设法找到了一个专门解决这个问题的 PEP,它恰好相对不为人知,可能是因为合理用途的子集非常狭窄。
我发现了一段优秀的示例代码,展示了新的 sys.meta_path
实现。我在下面 post 编辑了它以获取有关如何动态 bootstrap 您的导入语句的信息。
import sys
class VirtualModule(object):
def hello(self):
return 'Hello World!'
class CustomImporter(object):
virtual_name = 'my_virtual_module'
def find_module(self, fullname, path):
"""This method is called by Python if this class
is on sys.path. fullname is the fully-qualified
name of the module to look for, and path is either
__path__ (for submodules and subpackages) or None (for
a top-level module/package).
Note that this method will be called every time an import
statement is detected (or __import__ is called), before
Python's built-in package/module-finding code kicks in."""
if fullname == self.virtual_name:
# As per PEP #302 (which implemented the sys.meta_path protocol),
# if fullname is the name of a module/package that we want to
# report as found, then we need to return a loader object.
# In this simple example, that will just be self.
return self
# If we don't provide the requested module, return None, as per
# PEP #302.
return None
def load_module(self, fullname):
"""This method is called by Python if CustomImporter.find_module
does not return None. fullname is the fully-qualified name
of the module/package that was requested."""
if fullname != self.virtual_name:
# Raise ImportError as per PEP #302 if the requested module/package
# couldn't be loaded. This should never be reached in this
# simple example, but it's included here for completeness. :)
raise ImportError(fullname)
# PEP#302 says to return the module if the loader object (i.e,
# this class) successfully loaded the module.
# Note that a regular class works just fine as a module.
return VirtualModule()
if __name__ == '__main__':
# Add our import hook to sys.meta_path
sys.meta_path.append(CustomImporter())
# Let's use our import hook
import my_virtual_module
print my_virtual_module.hello()
完整博客 post 是 here