Python pathlib 深度实践:告别 os.path 的五种场景
日常脚本里处理文件路径,很多人还在用 os.path.join、os.path.exists 这一套。Python 3.4 引入的 pathlib 其实更简洁、更安全,本文用五个真实场景说明为什么该切换过去。
为什么不用 os.path
os.path 是函数式风格:你把字符串传进去,它返回字符串。问题是字符串不带类型信息,拼接时容易出错,比如忘了加分隔符、或者混用正反斜杠。pathlib 把路径变成一等对象,路径上的操作变成方法调用,链式可读。
# os.path 风格
import os
config = os.path.join(os.path.dirname(__file__), '..', 'config', 'app.yaml')
# pathlib 风格
from pathlib import Path
config = Path(__file__).parent / '..' / 'config' / 'app.yaml'
第二种写法用运算符重载,/ 直接拼接路径段,语义和 Shell 的路径分隔符一致,不需要记忆函数名。
场景一:批量查找并处理文件
假设要找出目录下所有 .log 文件,按修改时间排序后逐个压缩。
from pathlib import Path
import gzip, shutil
log_dir = Path('/var/log/myapp')
logs = sorted(log_dir.glob('*.log'), key=lambda p: p.stat().st_mtime)
for log in logs:
with log.open('rb') as src, gzip.open(f'{log}.gz', 'wb') as dst:
shutil.copyfileobj(src, dst)
log.unlink() # 删除原文件
glob 返回的是 Path 对象列表,可以直接调 .stat()、.open()、.unlink(),不用再包一层 os.path 调用。
场景二:递归查找嵌套目录
rglob 一行搞定递归:
# 找出项目里所有 __init__.py
inits = list(Path('.').rglob('__init__.py'))
os.walk 要手写循环,pathlib 只要一个方法名。配合列表推导还能加过滤条件:
large = [p for p in Path('.').rglob('*.py') if p.stat().st_size > 10000]
场景三:安全的路径拼接与规范化
路径里出现 … 或多余分隔符时,resolve() 会给出绝对的真实路径,还能帮你发现符号链接背后的真实位置:
p = Path('data/../config/./app.yaml')
real = p.resolve()
# /home/user/project/config/app.yaml
这在处理用户上传的文件名时尤其重要——先 resolve 再判断是否在允许目录内,能防止路径穿越攻击:
base = Path('/var/www/uploads').resolve()
target = (base / user_input).resolve()
if not str(target).startswith(str(base)):
raise ValueError('非法路径')
场景四:读写文件一行到位
Path 对象自带 read_text、write_text、read_bytes、write_bytes,适合脚本里快速读写小文件:
cfg = Path('config.yaml')
content = cfg.read_text(encoding='utf-8')
cfg.write_text(new_content, encoding='utf-8')
比 open() 少一层 with,代码更紧凑。注意大文件仍建议用 open 流式读写,这几个方法是整块读写的。
场景五:路径拆解与改名
Path 把路径拆成属性,比 os.path.split 系列更直观:
p = Path('/data/logs/2026-11-03/app.log')
p.parent # /data/logs/2026-11-03
p.name # app.log
p.stem # app
p.suffix # .log
p.parts # ('/', 'data', 'logs', '2026-11-03', 'app.log')
批量改后缀时用 with_suffix:
for f in Path('.').glob('*.jpeg'):
f.rename(f.with_suffix('.jpg'))
一个容易踩的坑
Windows 上 Path 的分隔符是反斜杠,但 Path 对象内部统一用正斜杠存储,打印时按系统转义。这意味着同一段代码在 Linux 和 Windows 上行为一致,不用再写平台判断。唯一要注意的是:如果你把 Path 对象传给只接受字符串的底层 API(比如某些 C 扩展),记得用 str() 转一下。
小结
os.path 并没有被废弃,但在新代码里优先用 pathlib 几乎没有缺点:更安全、更可读、跨平台。唯一例外是你要兼容 Python 3.3 及更早版本——那种场景现在越来越少了。从今天起,新脚本里第一行路径相关代码,试试写 from pathlib import Path 吧。
- 点赞
- 收藏
- 关注作者
评论(0)