我的包裹是这样的:
/mypackage
|-- __init__.py
|-- moduleA.py
|-- moduleB.py
|-- oldModule.py__init__.py看起来是这样的:
from mypackage.moduleA import abc
from mypackage.moduleB import jkl这使用户可以简单地按以下方式编写代码:
import mypackage as mpkg
mpkg.abc()
mpkg.jkl()默认情况下(使用上述import),用户无法访问oldModule.py中的函数。
这是因为95%的用户不需要这些东西(这是旧的)。
对于需要oldModule函数的5%的用户,他们可以编写:
from mypackage.oldModule import xyz
xyz()其中许多"oldModule“用户不需要访问__init__.py导入的函数
问题是,当用户只执行from mypackage.oldModule import xyz时
很明显,整个__init__.py也在运行。
我还能不能
from mypackage.oldModule import ...、或,则不会运行__init__.py,内部导入语句的结构吗?
这样我就可以检测到用户做了from mypackage.oldModule import ...,
然后,我可以使用__init__.py内部的一个__init__.py块来决定运行??的代码的哪些部分。谢谢。
发布于 2020-04-19 18:00:21
没有办法完全按照你的要求去做。导入some_package.some_module时,包总是在子模块之前完全加载。
但是,在您的案例中,可能有一些方法可以缓解这一问题。如果您想避免在用户寻找moduleA和moduleB时导入oldModule子模块,那么您可能会让它们的加载变得懒散,而不是急切。
从Python3.7开始,PEP 562允许模块有一个名为__getattr__的函数,它将像类中定义的同名方法一样工作。当查找模块的属性但未找到时,将使用名称调用__getattr__函数。
因此,在您的__init__.py文件中,您可以:
# from mypackage.moduleA import xyz don't do these imports unconditionally any more
# from mypackage.moduleB import abc
def __getattr__(name):
global xyz, abc
if name == 'xyz':
from .moduleA import xyz
return xyz
elif name == 'abc':
from .moduleB import abc
return abc
raise AttributeError(f"module {__name__} has no attribute {name}")如果您需要这样保护更多的名称(而不仅仅是两个),您可能需要编写更多的通用代码,它可以处理一个名称列表(可能每个子模块一个),并使用importlib正确地导入它们并直接写入包的__dict__中。这将比尝试使用global语句和为每个名称编写一个单独的if分支更方便。
https://stackoverflow.com/questions/61305031
复制相似问题