包 __init__.py 的相对导入
Posted
技术标签:
【中文标题】包 __init__.py 的相对导入【英文标题】:Relative import of package __init__.py 【发布时间】:2017-07-25 16:55:34 【问题描述】:假设我有一个包含两个子模块的包以及__init__.py
本身中的大量代码:
pkg/__init__.py
pkg/foo.py
pkg/bar.py
并且,为了使计划中的未来重构更容易,我希望包的组件专门使用相对导入来相互引用。特别是,import pkg
永远不应出现。
来自foo.py
我可以做
from __future__ import absolute_import
from . import bar
访问bar.py
模块,反之亦然。
问题是,以这种方式导入__init__.py
我要写什么? 我想要与import pkg as local_name
完全相同的效果,只是不必指定绝对名称pkg
。
#import pkg as local_name
from . import ??? as local_name
更新:受到 maxymoo 回答的启发,我尝试了
from . import __init__ as local_name
这不会将local_name
设置为__init__.py
定义的模块;相反,它获得了似乎是该模块的__init__
method 的绑定方法包装器。我想我能做到
from . import __init__ as local_name
local_name = local_name.__self__
得到我想要的东西,但是 (a) 很糟糕,并且 (b) 这让我担心模块还没有完全初始化。
答案需要在Python 2.7 和 Python 3.4+ 上工作。
是的,最好将__init__.py
挖空并让它从子模块中重新导出内容,但这还不能实现。
【问题讨论】:
【参考方案1】:dunders 并没有什么特别之处(他们只是在编写您自己的模块/函数名称时感到气馁);你应该能够做到
from .__init__ import my_function as local_name
【讨论】:
我不想从__init__.py
导入特定函数,我想要整个模块。
显式导入 __init__
模块会重新执行该模块,从而产生两个 不同 模块(pkg is pkg.__init__
为 False)。每个都有自己的命名空间。如果您更改 pkg
中的某些内容(比如 pkg.config.setSomeValue(...)
之类的内容),它不会影响 pkg.__init__
中的对应项。
@mata 这开始感觉像是一个错误报告:-/
@zwol 你能做from .__init__ import *
吗?
@maxymoo 不,这会将大量垃圾倾倒到子模块中,并且还需要大量而痛苦的代码更改。【参考方案2】:
python2和python3(使用discouraged__import__
):
来自第一级模块(pkg.foo
,pgk.bar
,...):
local_name = __import__("", globals(), locals(), [], 1)
来自子包中的模块 (pkg.subpkg.foo
, ...):
local_name = __import__("", globals(), locals(), [], 2)
仅限python3*:
来自pkg.foo
或pkg.bar
:
import importlib
local_name = importlib.import_module("..", __name__)
来自pkg.subpkg.baz
:
import importlib
local_name = importlib.import_module("...", __name__)
*import_module
在 python2 上尝试加载pkg.
,不幸的是。
【讨论】:
以上是关于包 __init__.py 的相对导入的主要内容,如果未能解决你的问题,请参考以下文章