python相对模块引入与相对文件路径
0x00 相对路径相对的是哪个路径
首先我们要知道python会参考两个路径分别是cwd
和path
,其分别可以通过
1 |
|
我们发现在导入模块和读取文件时相对的是不同路径,这在读取和导入不再同一父目录的文件和模块时尤为重要。
我们有一个project其目录结构如图:
1 |
|
0x01 cwd 工作目录
工作目录是python解释器运行的目录,程序去读取文件会更具cwd来寻找相对地址,且只会根据cwd,而与path无关
1
2
3
4
5
6# 在project目录下运行py文件
PS D:\tmp\project> python task/test1.py
this is project/task/test1.py, now cwd is D:\tmp\project and sys.path[0] is D:\tmp\project\task
# 在task目录下运行py文件
PS D:\tmp\project\task> python test1.py
this is project/task/test1.py, now cwd is D:\tmp\project\task and sys.path[0] is D:\tmp\project\task
0x02 sys path
sys
path第一项是python文件所在的目录,在导入模块时,会去搜索path中的地址和相对地址,且与cwd无关
1
2
3
4
5
6# 运行project目录下的test
D:\tmp\project> python test1.py
this is project/test1.py, now cwd is D:\tmp\project
# 运行project/task文件下的test
PS D:\tmp\project> python task/test1.py
this is project/test1.py, now cwd is D:\tmp\project and sys.path[0] is D:\tmp\project\task
0x03 根据相对地址导入模块
导入模块时相对的时sys.path中的地址。 ### 在task/test1.py导入test2.py
在跑一个项目时,看到他在导入同一目录下文件时使用的是以下代码,并且该写法vscode的静态语法检查不会报错。
1
2
3#file: project/task/test1.py
import task.test2.py1
2
3
4
5
6PS D:\tmp\project> & D:/ANACONDA/envs/GA/python.exe d:/tmp/project/task/test1.py
this is project/task/test1.py, now cwd is D:\tmp\project and sys.path[0] is d:\tmp\project\task
Traceback (most recent call last):
File "d:\tmp\project\task\test1.py", line 4, in <module>
import task.test2
ModuleNotFoundError: No module named 'task'
通过sys path第一项我们可以看到其在d:
解决办法
我们需要将父目录添加到环境变量中才能导入父目录这个文件夹。 * 方法1:
将导入修改为 1
import test2.py
1
2
3
4
5
6
7
8
9
10
11
12 "version": "0.2.0",
"configurations": [
{
"name": "Python 调试程序: 当前文件",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"env": {"PYTHONPATH":"${workspaceFolder}"},// 工作目录或者".."
"envFile": "${workspaceFolder}/.env"
}
],1
2cd ..
$env:PYTHONENV=$pwd
0x04 根据相对地址导入文件
我在网上查找了很多资料,都是人都说相对路径相对的是当前文件的路径,其实不然。从0x01
我们知道cwd
会随着python调用的改变而改变,即使文件地址不变,在不同目录调用使用python文件会读到不同的文件
实验表明读取文件的相对地址是相对于cwd
test1.py代码: 1
2
3
4
5import os
import sys
print(f"this is project/task/test1.py, now cwd is {os.getcwd()} and sys.path[0] is {sys.path[0]}")
with open("11.txt", "r") as f:
print(f.read())1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#在project目录中调用project/task/test1
PS D:\tmp\project> & D:/ANACONDA/envs/GA/python.exe d:/tmp/project/task/test1.py
this is project/task/test1.py, now cwd is D:\tmp\project and sys.path[0] is d:\tmp\project\task
i am project/11.txt
#在task目录中调用project/task/test1.py
this is project/task/test1.py, now cwd is D:\tmp\project\task and sys.path[0] is D:\tmp\project\task
i am project/task/11.txt
'''
python 文件修改为open("../11.txt", "r"),
'''
#在task目录中调用project/task/test1.py
PS D:\tmp\project\task> & D:/ANACONDA/envs/GA/python.exe d:/tmp/project/task/test1.py
this is project/task/test1.py, now cwd is D:\tmp\project\task and sys.path[0] is d:\tmp\project\task
i am project/11.txt
#在project目录中调用
this is project/task/test1.py, now cwd is D:\tmp\project and sys.path[0] is D:\tmp\project\task
Traceback (most recent call last):
File "D:\tmp\project\task\test1.py", line 4, in <module>
with open("../11.txt", "r") as f:
FileNotFoundError: [Errno 2] No such file or directory: '../11.txt'
'''
文件会报错,因为在project的父目录,也即D:\tmp中没有11.txt文件。
'''