0

使用 Python 3.3 或更高版本,我将如何创建并导入包含一组未指定模块的包?我希望导入包中的所有模块,而不必按名称导入每个模块。这将允许将新模块添加到包中,并且下次导入包时可以自动加载新模块,而无需对包进行任何其他更改。

从包的外部,我想导入和使用包看起来像这样:

import package
package.module.function()

从包的内部,我想导入和使用兄弟模块看起来像这样:

from . import sibling
sibling.function()

或这个:

import package.sibling
package.sibling.function()
4

1 回答 1

1

在 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 pkgutilto 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似乎没有简单的方法来识别可导入的模块和子包,除非可能通过导入所有内容并捕获错误,并且这些误报错误消息使得当模块无法导入时更难捕获合法问题。

于 2014-08-23T07:10:34.390 回答