python模块绝对引用和相对引用
python项目中的模块引用问题,是一个比较复杂的问题,无非是绝对引用,相对引用,看起来似乎很简单,但在实践中,总是会出现一些“莫名其妙”的错误,但解决起来倒也方便,import语句的写法多试验几次也就可以搞定了,关于这方面,很少有文章全面深入的讨论,我也是在这块吃过几次亏后,痛定思痛,决定认真研究一下。本文所使用示例在python3.7环境下顺利通过,如果文中观点有错误之处,请各位看官不吝赐教。
入口脚本
首先明确一点,一个项目的入口脚本,或者说启动脚本,必须放在项目的根目录下,启动脚本所在的目录,将被加入到sys.path里,而我们在脚本里使用import引入模块时,会根据sys.path里的目录逐个进行查找,这一点很关键,后面会用到。
pypackage/
├── __init__.py
├── log.py
├── run.py
├── utils
│ ├── fileutil.py
│ └── __init__.py
└── view
├── __init__.py
├── one.py
├── two.py
└── view2
├── four.py
├── __ini__.py
└── three.py
run.py 作为项目的启动脚本,放在了根目录下,它可以引用项目里的任意模块。
绝对引用
从层级上看,log.py也在根目录下,four.py 在view/view2目录下, 那么 four.py脚本里可以引入log模块么?答案是肯定的,因为启动脚本所在的目录,将被加入到sys.path里,因此在four.py 里可就可以这样写
import log
受此启发,fileutil 也可以引入four模块
from view.view2 import four
这里的关键就在于启动脚本所在的目录被加入到sys.path里
相对引用
如果我想在one.py 里引用two模块,除了绝对引用外,还可以使用相对引用
from view import two # 绝对引用
from . import two # 相对引用
如果我想在one.py 里引用fileutil 模块,讲道理的话,下面两种方法都可行
from utils import fileutil # 绝对引用
from ..utils import fileutil # 相对引用 实测不可行
一个. 表达式当前目录, 两个 .. 表示上一级目录,那么 from ..utils import fileutil 本应该也可行,但实测却发现无法引用,所以,遇到这种莫名其妙的问题,我建议你使用绝对引用,避免使用相对引用