在 Python 3.3 或更高版本中,使用 pkgutil 搜索包目录并使用 importlib 加载每个模块。
在包装中__init__.py
:
# Import standard modules.
import importlib
import os
import pkgutil
# For each module in the current directory...
for void, module_name, void in pkgutil.iter_modules([os.path.dirname(__file__)]):
# Import the module.
importlib.import_module(__name__+'.'+module_name)
上面的内容可以移动到一个库中,之后包__init__.py
就变得简单了:
# Import local modules.
import loader
# Load all modules in the current directory.
loader.load_all_modules(__file__,__name__)
请注意,该importlib
机制是在 Python 3.1 中引入的,并在 Python 3.3 中进行了重大更新,并且上述方法尚未在 Python 3.1.x 或 3.2.x 中进行测试。
https://docs.python.org/3.3/library/importlib.html#importlib.import_module
https://docs.python.org/3.3/library/pkgutil.html#pkgutil.iter_modules
其他失败的方法
尝试 1
从包外部,使用绝对导入:
import package.module
需要知道模块名称。
尝试 2
从包中__init__.py
,使用绝对导入:
import module
需要知道模块名称。
尝试 3
从包的__init__.py
,设置__all__
:
__all__ = ['module']
需要使用:
from package import *
这会污染命名空间并且在任何情况下都可能是危险的,但在这种情况下尤其危险,因为模块的名称是未知的。
尝试 4
从包的__init__.py
, using pkgutil
to identify and import all modules in package 似乎执行导入但仅模拟本机导入机制并且不更新sys.modules
字典。当包中的模块尝试导入同级模块时,这会导致问题,例如:
未列出sys.modules
会导致相对导入失败并显示以下消息:
父模块 '' 未加载,无法执行相对导入。
http://hg.python.org/cpython/file/f7992397e98d/Lib/importlib/_bootstrap.py#l1518
此外,绝对导入会重新加载正在导入的模块。
https://docs.python.org/3.3/library/imp.html#imp.load_module
http://python-notes.curiousefficiency.org/en/latest/python_concepts/import_traps.html#the-double-import-trap
尝试 5
从包的角度来看__init__.py
,使用importlib
似乎没有简单的方法来识别可导入的模块和子包,除非可能通过导入所有内容并捕获错误,并且这些误报错误消息使得当模块无法导入时更难捕获合法问题。