首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从__init__.py内部访问导入语句(或导入子模块时如何不运行__init__.py )

从__init__.py内部访问导入语句(或导入子模块时如何不运行__init__.py )
EN

Stack Overflow用户
提问于 2020-04-19 13:22:04
回答 1查看 50关注 0票数 0

我的包裹是这样的:

代码语言:javascript
复制
/mypackage
|-- __init__.py
|-- moduleA.py
|-- moduleB.py
|-- oldModule.py

__init__.py看起来是这样的:

代码语言:javascript
复制
from mypackage.moduleA import abc
from mypackage.moduleB import jkl

这使用户可以简单地按以下方式编写代码:

代码语言:javascript
复制
import mypackage as mpkg

mpkg.abc()
mpkg.jkl()

默认情况下(使用上述import),用户无法访问oldModule.py中的函数。

这是因为95%的用户不需要这些东西(这是旧的)。

对于需要oldModule函数的5%的用户,他们可以编写:

代码语言:javascript
复制
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块来决定运行??的代码的哪些部分。

谢谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-04-19 18:00:21

没有办法完全按照你的要求去做。导入some_package.some_module时,包总是在子模块之前完全加载。

但是,在您的案例中,可能有一些方法可以缓解这一问题。如果您想避免在用户寻找moduleAmoduleB时导入oldModule子模块,那么您可能会让它们的加载变得懒散,而不是急切。

从Python3.7开始,PEP 562允许模块有一个名为__getattr__的函数,它将像类中定义的同名方法一样工作。当查找模块的属性但未找到时,将使用名称调用__getattr__函数。

因此,在您的__init__.py文件中,您可以:

代码语言:javascript
复制
# 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分支更方便。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61305031

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档