【问题标题】:access to import statement from within __init__.py (or how to not run __init__.py when importing submodule)从 __init__.py 中访问 import 语句(或在导入子模块时如何不运行 __init__.py)
【发布时间】:2020-04-19 13:22:04
【问题描述】:

我的包裹看起来像这样:

/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 不会运行,
  • 我可以查看导入语句的结构__init__.py内部,
    以便我可以检测到用户做了from mypackage.oldModule import ...
    然后我可以在__init__.py 中使用if 块来决定要运行代码的哪些部分??

谢谢。

【问题讨论】:

    标签: python-3.x python-import python-importlib


    【解决方案1】:

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

    但可能有一些方法可以缓解这种情况在您的情况下导致的问题。如果您想避免在用户查找 oldModule 时导入 moduleAmoduleB 子模块,您可以让他们的加载变得懒惰,而不是急切地加载。

    从 Python 3.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 分支更方便。

    【讨论】:

    • 谢谢。会试一试的。
    猜你喜欢
    • 2014-09-08
    • 1970-01-01
    • 2016-06-14
    • 1970-01-01
    • 2015-07-30
    • 1970-01-01
    • 2013-07-29
    • 2019-05-29
    • 2018-10-27
    相关资源
    最近更新 更多