转载说明
Python中的相对文件路径的调用
作者:monitor1379
来源:简书
(修改部分代码和描述)
前言
先让我们来看看一个用到相对文件路径的函数调用的问题。假设现在有两个脚本文件main.py和func.py,他们的路径关系是:
.
|--dir1
|--main.py
|--dir2
|--func.py
|--test.txt
func.py
的作用是提供load_txt()
函数,读取同级目录下test.txt
文件中的内容并返回。
test.txt
这是test文件.
func.py
def load_txt():
# 相对路径起始目录为func.py所在目录
filename = 'test.txt'
# 包含中文时,注意与读取的文件编码保持一致
with open(file_path, 'r', encoding='utf-8') as file:
content = file.read()
return content
main.py
main.py中调用load_txt()函数:
from dir2 import func
if __name__ == '__main__':
print func.load_txt()
这个时候会报类似找不到文件test.txt的错误。
FileNotFoundError: [Errno 2] No such file or directory: './test.txt'
为什么会这样呢?
这是因为在函数调用的过程中,当前路径
是被执行的脚本文件(主程序文件)的所在位置
。在这个情况中,.表示的就是 main.py 的所在路径,所以load_txt()
函数会在dir1
文件夹中寻找test.txt
文件。
那么,怎么样才能在函数调用的过程中保持当前路径的不变呢?
解决方法
在网上有相当多的教程都有提到这个Python中相对文件路径的问题,但是大部分都没有提及到在这种情况下的解决办法。
以下是有关当前路径在四个函数,添加到 func.py 中
import os
import sys
def get_cur_path1():
path = os.path.abspath(os.curdir)
return convert_path(path)
def get_cur_path2():
path = os.path.abspath(os.getcwd())
return convert_path(path)
def get_cur_path3():
path = sys.argv[0]
return convert_path(path)
def get_cur_path4():
path = os.path.dirname(__file__)
return convert_path(path)
#把任意系统的路径转换成当前系统的格式
#https://blog.csdn.net/lnotime/article/details/87720332
def convert_path(path: str) -> str:
# seps = r'\/'
# # 保留非系统分隔符,即需要替换的分隔符
# sep_other = seps.replace(os.sep, '')
# # 使用in 遍历依次检查替换为系统分隔符
# return path.replace(sep_other, os.sep) if sep_other in path else path
# 判断 in 也是需要遍历,replace又要遍历,还不如不判断 in 直接使用replace效率更高
return path.replace(r'\/'.replace(os.sep, ''), os.sep)
在 main.py 中进行测试
from dir2 import func
if __name__ == '__main__':
print(func.get_cur_path1())
print(func.get_cur_path2())
print(func.get_cur_path3())
print(func.get_cur_path4())
# print(func.load_txt())
结果如下:
F:\Practice\PycharmProjects\PythonOOP\_10_文件操作\dir1
F:\Practice\PycharmProjects\PythonOOP\_10_文件操作\dir1
F:\Practice\PycharmProjects\PythonOOP\_10_文件操作\dir1\main.py
F:\Practice\PycharmProjects\PythonOOP\_10_文件操作\dir1\dir2
第一个
、第二个
和第三个
是大部分教程中的解决办法,明显都是错的
第一个
和第二个
所获取的当前文件路径
都是被执行的脚本文件(即程序入口,主程序文件)所在目录
第三个
是主程序文件的完整路径
只有第四个
函数返回的当前文件路径才是真正的函数所在的脚本文件的所在路径
因此,解决办法如下。修改 func.py 中的读取函数如下即可:
func.py
import os
def load_txt():
# 相对路径起始目录为func.py所在目录
filename = 'test.txt'
file_dir = os.path.dirname(__file__)
# # 使用系统分隔符连接目录和文件
# file_path = os.sep.join([file_dir, filename])
# 使用路径模块连接
file_path = os.path.join(file_dir, filename)
# 包含中文时,注意与读取的文件编码一致,
with open(file_path, 'r', encoding='utf-8') as file:
content = file.read()
return content
重新执行 main.py
from dir2 import func
if __name__ == '__main__':
# print(func.get_cur_path1())
# print(func.get_cur_path2())
# print(func.get_cur_path3())
# print(func.get_cur_path4())
print(func.load_txt())
结果如下:
这是test文件.