绝对路径导入格式为
import a.b
或者from a import b
,相对路径导入格式为from . import b
或者from ..a import b
。python2默认为相对路径导入,python3默认为绝对路径导入。
为使python2,3通用,建议采用相对路径导入
from .a import b
一个目录存在
__init__.py
文件,则该目录成为一个包。包中的一个模块可以采用相对路径导入包,不影响模块功能;一个py脚本(未成为模块,即其目录及父目录内无
__init__.py
)可以采用相对路径导入包,并以脚本模式运行。但包含相对导入的模块,不能直接以脚本模式运行,常见报错为:
# python2
Traceback (most recent call last): File "module_x.py", line 1, in <module> from . module_y import spam as ham ValueError: Attempted relative import in non-package
# python3
Traceback (most recent call last): File "module_x.py", line 1, in <module> from . module_y import spam as ham SystemError: Parent module '' not loaded, cannot perform relative import
解决方案:
建立示例文件结构如下:
注:以/
结尾的为文件夹。
/home/zhkai/
mobike/
__init__.py
utils.py
data_process/
loc.py
注意此时mobike成为一个python包。
在loc.py
中导入utils.py
该怎么办?
方法1:将mobike包导入系统路径
在loc.py
中导入util
的方法为:
import sys
sys.path.append('/home/zhkai')
from mobike.utils import read_csv
需要注意,这里导入系统路径的是mobike所在目录的路径,路径本身不包含mobike。
此时utils
就像自带的python包一样,loc.py
可直接运行。
【推荐】方法2:修改运行命令
python的man page里有这个参数:
-m module-name
Searches sys.path for the named module and runs the corresponding .py file as a script.
所以可以在不修改模块代码文件的情况下:
代码文件仍为相对路径:
from ..utils import read_csv
切换到mobike包同级目录下执行:
☁ ~ python3 -m mobike.data_process.loc
注意:此时若loc.py代码中有其他相对路径,此时的相对路径是基于shell命令所在位置,即
~
的,可能会造成错误。import语句中的相对路径,仍是基于文件所在位置,故不影响。
推荐这种方法,因为无需修改代码文件。
还有句话不太理解:如果一个模块被直接运行,则它自己为顶层模块,不存在层次结构,所以找不到其他的相对路径。