首先介绍几个知识点,虽然不一定相关,但就是想科普下:
- 凡是规范的python代码开头都是如下两行
第一行:使用env命令中的PATH环境变量,查找python解释器来执行此python代码
第二行:指定当前脚本编码为UTF-8
#!/usr/bin/env python
# -*- coding:UTF-8
__name__
这个python内建属性表示当前模块执行过程中的名称,如果当前模块是程序的入口,name 的名称就是main如果不是,则为这个模块的名称。sys模块
包含了与python解释器和它的环境有关的函数sys.path
模块搜索路径的集合,导入模块时,依次从这个集合中查找,默认的顺序如下:- 当前目录
- PYTHONPATH环境变量
- Python 安装路径的lib库
- 通过代码自定义的路径
可以通过修改它,将自己模块的路径加入到搜索列表中
sys.modules
一个全局字典,在python启动后加载在内存中。导入新的模块时sys.modules将自动记录该模块。当再导入该模块时,python会直接到字典中查找。
正片开始
包和模块
python中一个代码文件就是一个模块,把模块组织起来就是包,包在实际的的文件系统中就是一个目录(文件夹),和一个__init__.
py文件,包的名字就是目录的名字
导入
绝对导入
性质 解释 特点 从sys.path记录的目录中查找模块,顺序参见上面,Python3中是默认导入方法 格式 import base.modul
或from base import modul
优点 官方推荐做法,在程序任何地方都能使用绝对导入,而且可以避免覆盖内置模块 相对导入
性质 解释 特点 方便的导入当前目录、上一级、上上一级目录等等,比较特殊的是:相对导入适用场景是在包内,所有的目录都必须在同一个顶层包里面,Python2的默认导入方法,也就是说在Python2的一个包内部导入模块: import modul
等于from . import modul
格式 from . import modul
或from ..base import modul
.
代表当前目录,..
代表上级目录,...
以此推类优点 避免硬编码,对于包的维护是友好的
难点讲解
- 在程序入口目录下的代码中使用:
import modul
都是绝对导入,因为相对导入是适用在包内,而入口目录不是一个包。此时使用相对导入就会报错。 - 在包内的代码中使用
import modul
,如果是Python2,默认是相对导入,等于:from . import modul
,如果是Python3则会报错,因为Python3默认使用绝对导入不会自动转化为:from . import modul
- 直接执行含有相对导入的Python文件会报错,原因同第一个问题
最后
推荐大家所有都使用绝对导入,忘掉相对导入这个概念吧,原则上包的名字在确定过后就不能改动,所以它带来的那一点点好处也没太大的价值,还会带来很多坑等着。