我有如下包结构
package
__init__.py
sub1
__init__.py
foo.py # Contains class Foo
sub2
__init__.py
bar.py # Contains class Bar
我希望能够只import package
并拥有package.Foo
和package.Bar
,即我想要子包对用户透明。
问题是导入sub2需要很长时间,很多用户根本不关心sub2里的东西,只想要sub1里的东西。因此,我希望用户能够说import package.sub1
或from package import sub1
到just import sub1 并跳过sub2 的导入。
我知道我可以通过包含 package/__init__.py
来实现第一部分
from .sub1 import *
from .sub2 import *
并且 package/sub1/__init__.py
是 from .foo import Foo
和 sub2 类似。但是,这将始终导入 sub1 和 sub2,即使用户尝试仅导入 package.sub1
。
相应地,我可以通过让 package/__init__.py
为空并使用与上面相同的 sub1/__init__.py
来实现第二部分。但是,只是说 import package
不会加载 sub1 或 sub2,因此用户必须显式加载它们,然后引用 package.sub1.Foo
。
理想情况下,一个解决方案在 2.7.10 和 3.5.0 中都适用,但如果两者都不可能,我会接受一个或另一个。
最佳答案
LazyLoader
类正是为这种情况提供的:在实际使用模块时推迟加载模块,而不是在导入模块时。
要构建延迟加载器,您可以按照文档中的示例进行操作:
suffixes = importlib.machinery.SOURCE_SUFFIXES
loader = importlib.machinery.SourceFileLoader
lazy_loader = importlib.util.LazyLoader.factory(loader)
finder = importlib.machinery.FileFinder(path, [(lazy_loader, suffixes)])
然后你可以使用finder.find_spec
获取模块的规范并将结果传递给Loader.create_module
加载它。
仅对一个模块手动操作有点麻烦。
请注意,搜索“lazy import python”,您会发现很多解决方案各有利弊,其中一些在 python2.x 中运行。然而,上面的 LazyLoader
类是 python3.5+ 中的官方方式
关于Python只导入一个子包而不导入其他子包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33452096/