【发布时间】:2016-01-31 19:54:57
【问题描述】:
我有以下包结构
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 只需 导入 sub1 并跳过 sub2 的导入。
我知道我可以通过包含 package/__init__.py 来实现第一部分
from .sub1 import *
from .sub2 import *
并且将package/sub1/__init__.py 设置为from .foo import Foo,对于sub2 也是如此。但是,即使用户尝试仅导入 package.sub1,这也将始终导入 sub1 和 sub2。
相应地,我可以通过让package/__init__.py 为空并使用与上面相同的sub1/__init__.py 来实现第二部分。但是,仅仅说import package 不会加载 sub1 或 sub2,因此用户必须显式加载它们,然后引用 package.sub1.Foo。
理想情况下,一个解决方案在 2.7.10 和 3.5.0 中都适用,但如果两者都不可行,我会接受其中一个。
【问题讨论】:
-
一个更好的问题是为什么
sub2中有一个模块级别的长时间运行代码 -
所以,事实上,你的问题是:“我希望
import package.sub1比import package做的事情更少,对吧?没有像提前读取字节码这样的奇怪技巧,我认为这是不可能。import A.B必须首先import A。注意docs.python.org/3.6/library/importlib.html 底部(最后一个代码块,第 15 行),import_module是一个递归函数。但是,您可以轻松拥有第三个子包,package.everything,这将真正将sub1和sub2导入到同一个命名空间中。 -
@Veky:这确实是我最终所做的(嗯,
package.all,但足够接近) -
.all 是我的第一个想法,但我决定反对它,因为它 a) 会引起与
package.__all__的错误关联,并且 b) 对于你不想鼓励的东西来说有点太短了人们去做(一个有吸引力的麻烦)。
标签: python packages python-import python-module