文件路径处理(os.path 与 pathlib)

1、知识点

如果把文件操作比作寄快递,os.path 就像手写地址——你得自己拼接、判断、拆分;pathlib 则像智能地址簿——面向对象,一路点到底,写法更优雅。

概念对比

需求 os.path 写法 pathlib 写法 (Path对象)
路径拼接 os.path.join(base,"sub","file.txt") base / "sub" / "file.txt"
获取文件名 os.path.basename(p) Path(p).name
获取后缀 os.path.splitext(p)[1] Path(p).suffix
获取父目录 os.path.dirname(p) Path(p).parent
判断是否存在 os.path.exists(p) Path(p).exists()
判断是文件 os.path.isfile(p) Path(p).is_file()
判断是目录 os.path.isdir(p) Path(p).is_dir()
获取绝对路径 os.path.abspath(p) Path(p).resolve()
遍历目录 os.listdir(p) Path(p).iterdir()
创建目录 os.makedirs(p, exist_ok=True) Path(p).mkdir(parents=True, exist_ok=True)

两种路径分隔符

  • Windows 用反斜杠 \,但 Python 字符串里 \ 是转义符,所以要么写 \\,要么写原始字符串 r"C:\Users"
  • pathlib 自动处理跨平台分隔符,一套代码 Windows / macOS / Linux 通吃。

关键区分

  • 相对路径:相对于当前工作目录,如 "data/file.txt"
  • 绝对路径:从根目录开始,如 "C:\\Users\\15740\\Desktop"
  • Path.cwd()os.getcwd() 查看当前工作目录

代码示例

import os
from pathlib import Path

# ============================================
# 准备工作:创建演示用的目录和文件
# ============================================
demo_dir = Path("demo_playground")
demo_dir.mkdir(exist_ok=True)                    # 创建目录,已存在不报错

# 创建几个测试文件
(demo_dir / "报告.docx").touch()                 # touch() 创建空文件
(demo_dir / "数据.csv").touch()
(demo_dir / "脚本.py").touch()
(demo_dir / "图片.png").touch()

# 在子目录下也创建文件
sub_dir = demo_dir / "备份"
sub_dir.mkdir(exist_ok=True)
(sub_dir / "config.ini").touch()

# ============================================
# 1. 路径拼接 —— 推荐用 pathlib 的 /
# ============================================
# os.path
os_path = os.path.join("demo_playground","备份","config.ini")
print(f"[os.path 拼接]:{os_path}")

#pathlib :直接用 / 运算符
pl_path = demo_dir/"备份"/"config.ini"
print(f"[pathlib 拼接]  {pl_path}")

# ============================================
# 2. 路径信息拆解
# ============================================
p = Path("demo_playground/报告.docx")

print(f"\n[文件信息] {p}")
print(f" 文件名(含拓展名):{p.name}")
print(f"后缀名:{p.suffix}")
print(f"去掉后缀的文件名:{p.stem}")
print(f"父目录:{p.parent}")
print(f"绝对路径:{p.resolve()}")

# ============================================
# 3. 遍历目录与筛选文件
# ============================================

print("\n[遍历 demo_playground]")

#glob 模式:只找.py和。csv文件
for f in demo_dir.glob("*.py"):
    print(f"python文件:{f.name}")
print()
# rglob 递归匹配:找所有 .ini 文件(包括子目录)
for f in demo_dir.rglob("*.ini"):
    print(f"配置文件(递归): {f}")
# ============================================
# 4. 创建与判断
# ============================================
new_folder = Path("自动创建新的文件夹")
new_folder.mkdir(exist_ok=True)
print(f"\n{'存在' if new_folder.exists() else '不存在'}: {new_folder}")
print(f"是目录吗? {new_folder.is_dir()}")
print(f"是文件吗? {new_folder.is_file()}")

# ============================================
# 5. 路径修改 —— with_suffix / with_name
# ============================================

old= Path("报告.docx")
new=old.with_suffix(".pdf")          # 只换后缀
print(f"\n改后缀:{old}——>{new}")

renamed=old.with_name("测试.docx")           # 完全换文件名
print(f"改文件名: {old}{renamed}")

# ============================================
# 清理演示文件(取消下行注释即可删除)
# ============================================
import shutil
shutil.rmtree(demo_dir)
new_folder.rmdir()
print("\n演示结束。如需清理临时文件,取消脚本末尾的注释即可。")

逐行关键说明

说明
demo_dir / "备份" pathlib 的灵魂操作——用 / 拼接路径,直观不费脑
.touch() 快速创建空文件,测试时特别好用
.name / .suffix / .stem 三个属性拆出文件名、后缀、纯名
.glob("*.py") 通配符匹配,和命令行 ls *.py 一样顺手
.rglob("*.ini") 递归版 glob,自动钻进所有子目录
.with_suffix(".pdf") 只换后缀不改目录,生成输出路径时很常用
.mkdir(exist_ok=True) exist_ok=True 是安全锁,目录已存在也不报错,省去 if 判断

补充

  1. PurePath vs Path:pathlib 分为 PurePath(纯路径运算,不访问磁盘)和 Path(会真正调用系统 API)。如果你只想做路径字符串的拼接、拆解,PurePath 更轻量。

  2. pathlib 与 open 配合Path 对象可以直接传给 open()——open(Path("data.txt")) 等价于 open("data.txt"),还能用 .read_text() / .write_text() 一行搞定读写。

  3. os.scandir() 性能:如果目录文件极多(数万级),os.scandir()os.listdir() 快很多,因为它一次系统调用拿回文件属性,不用逐个 stat。pathlib 的 .iterdir() 底层已使用 scandir。

  4. 跨平台坑:Windows 最大路径长度默认 260 字符,长路径需要注册表开启或使用 \\?\ 前缀。Python 3.6+ 的 pathlib 对此有部分支持,深层嵌套目录建议控制路径长度。

更多推荐