视频链接:

https://space.bilibili.com/70431433?spm_id_from=333.1007.0.0

文章代码链接:

https://github.com/zyf-ngu/Qmatter

文件路径

在学习关于路径的各种操作之前,我们首先明确路径是什么,能不能细分。路径保存文件或文件夹所在位置的信息,比如data/documents/report.txt,分为2部分,目录和文件名/文件夹名,第一部分是从根目录开始一直到最后一个斜杠之前的内容,这是目录;第二部分则是文件名(含扩展名),或者是文件夹名,或者为空。路径就好比是某个小区某单元某楼层某房间号,可以确认住户的位置信息,住户的名字即为文件名,男女可类比为扩展名;也可以不精确到人,把房间号作为文件夹名,房间号前面的为目录。

基本操作

文件路径也是要从基本的操作学习:

创建:路径(包含文件)与目录(不包含文件)

获取:拆分文件路径

验证:判断路径/目录是否存在;

路径的基本操作在Python里有2种实现方式,一种是传统的os.path模块,另一种是Python 3.4之后引入的pathlib模块,需要注意的是,os模块操作的是字符串,数据类型是str,而pathlib模块提供了面向对象的路径操作方式,数据类型是Path,二者混合使用时要记得进行数据类型转换。 

import os

from pathlib import Path 

在Python中,处理文件路径的基本操作通常涉及以下几个方面:

拼接路径:把文件所属的各级目录以及文件名和扩展名组合起来,创建路径之后,该路径下并不存在空文件,后面需要对文件进行操作。

#os.path.join函数跨平台安全拼接或使用字符串拼接

file_path1 = os.path.join("data", "documents", "test.txt")
file_path2 = Path("data2")/ "documents" / "report.txt" # 自动处理路径分隔符

 # 输出: data/documents/report.txt(Windows 下为data\documents\report.txt)

需要注意的是各级目录是分开的还是自身就已使用斜杠符号连接起来了。

创建目录:创建文件所在的目录即文件夹,不是文件。(这里注意区分os模块的makedirs和path模块下的mkdir操作均是递归创建多层)

os.makedirs(dir_path3, exist_ok=True) # exist_ok=True 避免目录已存在时报错

dir_path4.mkdir(parents=True, exist_ok=True)

创建文件

(1)创建空文件

如果只需要创建一个空文件,可以用以下简化方式:

# 方法1:使用open()

open('file_path1', 'w').close()

# 方法2:使用pathlib

Path('file_path2').touch()  # touch()方法模拟Unix的touch命令

(2)使用内置的 open() 函数(最常用)

通过写入模式打开文件,如果文件不存在会自动创建。

# 方法1:文本模式创建(默认)

with open('file_path1', 'w', encoding='utf-8') as f:

           f.write('这是通过open()创建的文本文件')

# 方法2:二进制模式创建

with open('image.bin', 'wb') as f:

          f.write(b'\x00\x01\x02')  # 写入二进制数据

'w':文本模式,覆盖已有内容(不存在则创建)

'a':文本模式,追加内容(不存在则创建)

'x':文本模式,仅创建新文件(如果文件已存在会报错)

加上 b 后缀(如 'wb')表示二进制模式

(3)使用 pathlib.Path的write_text()函数

# 方法1:直接写入内容

file_path2.write_text('这是通过pathlib创建的文本文件', encoding='utf-8')

# 方法2:二进制写入

bin_path = Path('data.bin')

bin_path.write_bytes(b'\x03\x04\x05')

# 检查路径存在 :判断该路径是否存在(包括文件和纯目录)。操作文件前先检查路径是否存在 写文件时目录不存在会触发 FileNotFoundError

exists = os.path.exists(path)

exists = file_path.exists()

# 输出: True

获取文件名:从已知路径中提取文件名(包括扩展名)或仅提取文件名(不含扩展名)。

# 获取文件名(带扩展名)

filename = os.path.basename(path)

filename = dir_path.name

# 输出: report.txt

# 获取文件名(不带扩展名,其本质是将文件名进行切分得到文件名和扩展名的列表,然后取列表的第一个值)

filename_no_ext = os.path.splitext(filename)[0] 或者os.path.split(‘.’)[0]

filename_no_ext = file_path.stem 

# 输出: report

获取目录名:从已知路径中提取目录部分。

dir_path = os.path.dirname(path)

dir_path = file_path.parent 

# 输出: data/documents

上面获取目录以及文件名就涉及到路径的拆分,将路径拆分成目录和文件名2部分。

路径的拆分和组合:使用os.path.split、os.path.splitext等函数拆分路径。

获取当前工作目录:根据当前运行代码所在的路径和文件名称获取文件所在的目录;

current_dir = os.getcwd() # 返回当前Python脚本的工作路径

# 获取绝对路径 

relative_path = "demo.txt"

abs_path = os.path.abspath(relative_path) # 将相对路径转为绝对路径

这个绝对路径前面的目录是当前工作目录,隐式获得的。其本质是将一个路径进行了拆分,一般是将从根目录到当前文件所在的目录得到相对目录,然后获取基于这个目录的相对文件位置。

# 将绝对路径改为相对路径:

if os.path.isabs(abs_path2):

    rel_path = Path(abs_path2).relative_to(current_dir1)

    print('rel_path',rel_path)

删除路径/目录

在Python中,删除文件或目录有两种常见的方法:

删除文件:,不能删除目录

os.remove()&dir_path.unlink()

删除空目录:

os.rmdir()&dir_path.rmdir()

删除目录(包括非空目录):递归删除整个目录树,即目录下的所有子目录和文件都会被删除

shutil.rmtree()

关键操作对比表

操作

os.path 方式

pathlib 方式

路径拼接

os.path.join("a", "b", "c.txt")

Path("a") / "b" / "c.txt"

获取文件名(带扩展名)

os.path.basename(path)

path.name

获取文件名(无扩展名)

os.path.splitext(name)[0]

path.stem

获取父目录

os.path.dirname(path)

path.parent

创建目录

os.makedirs(path, exist_ok=True)

path.mkdir(parents=True, exist_ok=True)

注意事项 

跨平台兼容性 

使用 os.path.join() 或 pathlib 的 / 运算符可自动处理 Windows(\)和 Linux/macOS(/)的路径分隔符差异,Windows路径前加个r可以识别

避免手动拼接路径(如 "data" + "/" + "file.txt")

文件编码 

默认使用系统编码(可能引发乱码) 显式指定编码更安全:Path.read_text(encoding="utf-8")

路径规范化 

使用 os.path.normpath() 或 Path.resolve() 解析相对路径和符号链接 推荐:

新项目优先使用 pathlib,提供更面向对象和简洁的 API,减少代码量 30% 以上。

文件夹遍历os.listdir(path)和os.walk(root) 

在深度学习中,常用的一种操作是遍历很多张图片处理做成数据集,这里就需要遍历文件夹的函数,一般有两个方法,os.listdir(path),会将路径下的文件夹以及文件名称储存到列表里,但不会递归到子文件夹里。

深度学习数据集的文件夹通常是多级的,比如图片是分类存放的,就有主文件夹,类别子文件夹,然后是图片文件,这时更常用的是os.walk(root),一般和for循环结合使用。会先遍历根文件夹得到根文件夹路径,以及下面的一级子文件夹路径列表(没有则为空)和一级子文件列表(没有则为空),返回的是一个深度递归的三元组(path,dirnames,filenames),然后把每一个子文件夹作为根目录继续深度循环遍历。

举个例子,

-dir1

-1.jpg

-subdir1

--2.jpg

--3.jpg

-subdir2

--4.jpg

--5.jpg

如果是os.listdir(dir1),输出就是1.jpg,subdir1,subdir2。

而for root,dir,file in os.walk(dir1) : 

第一次循环遍历输出三元组

(dir1 [subdir1,subdir2],[1.jpg])for循环的root,dir,file分别来承接元组的三个变量; 

第二次遍历输出三元组

dir/subdir1,[],[2.jpg,3.jpg]

第三次遍历输出三元组

dir/subdir2,[],[4.jpg,5.jpg]

os.mkdir 和os.makedirs的联系和区别是什么

在 Python 的 os 模块中,os.mkdir() 和 os.makedirs() 都是用于创建目录的函数,但它们的功能和使用场景有所不同,具体联系和区别如下:

联系

  • 两者的核心作用相同:均用于在文件系统中创建目录(文件夹)。
  • 都需要传入一个路径参数,指定要创建的目录位置。
  • 若目标目录已存在,调用时都会抛出 FileExistsError 异常。

区别

特性

os.mkdir(path)

os.makedirs(path, exist_ok=False)

功能

仅能创建单个目录(最底层目录)。

可以创建多级目录(包括中间不存在的目录)。

对父目录的要求

要求路径中的所有父目录必须已存在,否则抛出 FileNotFoundError。

自动创建路径中所有不存在的父目录,无需手动提前创建。

参数差异

无额外重要参数。

有 exist_ok 参数(默认 False):
- 若设为 True,目标目录已存在时不会抛出异常;
- 若设为 False(默认),目标目录已存在时抛出 FileExistsError。

适用场景

仅创建单级目录,且父目录已存在的场景。

需要创建多级目录(如 a/b/c),或不确定父目录是否存在的场景。

os.path.dirname(__file__)

__file__,指代当前运行的代码文件。

KB_ROOT_PATH=os.path.join(os.path.dirname(os.path.dirname(__file__)),'knowledge-base')这行代码用于动态获取项目中 knowledge-base 目录的绝对路径,其含义可拆解为以下几个部分:

__file__:

这是 Python 的内置变量,表示当前脚本文件(即包含这行代码的 .py 文件)的相对路径或绝对路径(取决于执行脚本的方式)。例如,若当前脚本路径为 D:/RAGPro/server/config.py,则 __file__ 的值为 'D:/RAGPro/server/config.py'。

os.path.dirname(path):

返回 path 路径中目录部分(即去掉文件名,保留上级目录)。例如:

若 path = 'D:/RAGPro/server/config.py',则 os.path.dirname(path) 返回 'D:/RAGPro/server'。

os.path.join(path1, path2):

用于拼接两个路径,自动适配当前操作系统的路径分隔符(Windows 用 \,Linux/macOS 用 /)。

路径计算过程拆解

假设当前脚本(包含这行代码的文件)的路径为:
D:/RAGPro/server/config.py

则代码的计算步骤如下:

第一次 os.path.dirname(__file__):
对 __file__('D:/RAGPro/server/config.py')取目录,得到 'D:/RAGPro/server'(当前脚本所在的目录 server)。

第二次 os.path.dirname(...):

对上一步结果('D:/RAGPro/server')再次取目录,得到 'D:/RAGPro'(server 的上级目录 RAGPro)。

os.path.join(...) 

拼接路径:将上一步的结果('D:/RAGPro')与 'knowledge-base' 拼接,最终得到:
'D:/RAGPro/knowledge-base'

as_posix()

pathlib 模块中 Path 对象的一个方法as_posix(),用于将路径转换为 POSIX 格式(使用正斜杠/作为分隔符的字符串),即在 Windows 上:将反斜杠 \ 转换为正斜杠 /;在 Linux/macOS 上:保持不变(因为已经是 POSIX 格式),它在跨平台开发中特别有用,保证路径格式的一致性。操作返回字符串(不是 Path 对象)

# Windows 路径示例

win_path = Path(r"C:\Users\Alice\文档\file.txt")

print(win_path.as_posix())  

# 输出: C:/Users/Alice/文档/file.txt

# Linux/macOS 路径示例

linux_path = Path("/home/alice/文档/file.txt")print(linux_path.as_posix())  

# 输出: /home/alice/文档/file.txt

# 混合路径示例

mixed_path = Path("C:\\Users/Bob\\文件//report.docx")print(mixed_path.as_posix())  

# 输出: C:/Users/Bob/文件/report.docx

更多推荐