如何从子包内实现绝对导入?
我对包中的导入有些困惑。想象一下,我有以下的文件夹结构:
pack ├── __init__.py ├── sub1 │ ├── __init__.py │ └── mod1.py └── sub2 ├── __init__.py └── mod2.py
在mod1.py文件里,我有以下代码来导入mod2.py:
# mod1.py
import pack.sub2.mod2
pack.sub2.mod2.helloworld()
我在包含pack的目录下有一个main.py文件,它导入了pack/sub1/mod1.py。
那么,mod1.py是怎么访问到pack的呢?因为pack并不在mod1.py的同一个目录下。Python会自动把最上层的包添加到sys.path里吗?
1 个回答
你可以通过在交互式解释器中查看 sys.path
来了解这个问题。你会发现它的第一个元素是解释器被告知要运行的脚本的位置。这意味着,当你在顶层(也就是 pack
包的位置)运行你的脚本时,这个位置会自动添加到 sys.path
中。这和实际的包结构没有关系,所以如果你直接运行 mod1.py
脚本,可能会导致一些问题(这可能就是你把脚本放在顶层的原因!)。
需要注意的是,在 Python 2 中,还有一个隐式相对导入的问题,这虽然和你问的问题没有直接关系,但如果涉及到更多模块时可能会出现。如果你把 mod3.py
加到 sub1
中,你可以在 mod1
中直接用 import mod3
来导入,前缀 pack.sub1
会自动处理。这个隐式行为通常被认为是不好的,在 Python 3 中是不允许的(在 Python 2 中你也可以通过 from __future__ import absolute_import
来禁用它)。如果你想从 pack.sub1.mod1
导入 pack.sub1.mod3
,你需要完整地写出名字,或者使用显式的相对导入:from . import mod3
回到你的问题,如果你想避免依赖 pack
在 sys.path
中(或者更实际地说,保护 pack
名称的变化),你可以把从 mod1
导入 mod2
的方式改成显式的相对导入。只需使用 from .. import sub2.mod2
。