Python-Pathlib库

news/2025/9/20 0:52:07/文章来源:https://www.cnblogs.com/aaooli/p/19101905

Python Pathlib 库指南

Pathlib 是 Python 3.4+ 中引入的面向对象的文件系统路径处理库,提供了比传统 os.path 更直观、更 Pythonic 的方式来处理文件路径和文件系统操作。

目录

  1. 1. Pathlib 核心概念
  2. 2. 路径操作详解
  3. 3. 文件系统操作
  4. 4. 目录遍历与模式匹配
  5. 5. 高级路径处理
  6. 6. 跨平台开发
  7. 7. 性能优化
  8. 8. 与传统模块对比
  9. 9. 最佳实践
  10. 10. 常见问题解决

1. Pathlib 核心概念

1.1 Path 对象类型

Pathlib 提供了两种主要路径类型:

具体路径类:实际访问文件系统

  • WindowsPath:Windows 系统专用
  • PosixPath:Unix/Linux/MacOS 系统专用

纯路径类:不访问文件系统

  • PureWindowsPath
  • PurePosixPath
from pathlib import Path, PurePath# 自动选择适合当前系统的路径类型
p = Path('file.txt')  # WindowsPath 或 PosixPath# 创建纯路径对象
pure_path = PurePath('/usr/bin/python')

1.2 Path 对象特性

  • 不可变对象:所有操作返回新路径对象
  • 链式操作:支持方法链式调用
  • 路径归一化:自动处理路径分隔符和冗余部分

2. 路径操作详解

2.1 路径创建与拼接

# 创建绝对路径
abs_path = Path('/home/user/docs')# 创建相对路径
rel_path = Path('src/utils')# 使用家目录
home_path = Path.home()  # /home/user 或 C:\Users\User# 拼接路径
config_path = home_path / '.config' / 'app' / 'settings.ini'# 使用 joinpath
log_path = Path('logs').joinpath('2023', 'app.log')

2.2 路径组件访问

p = Path('/home/user/docs/report.tar.gz')p.name         # 'report.tar.gz'
p.stem         # 'report.tar' (Python 3.9+)
p.suffix       # '.gz'
p.suffixes     # ['.tar', '.gz']
p.parent       # Path('/home/user/docs')
p.parents      # 生成器: [Path('/home/user/docs'), Path('/home/user'), ...]
p.anchor       # '/' 或 'C:\\'
p.drive        # '' 或 'C:' (Windows)
p.root         # '/' 或 '\\' (Windows)

2.3 路径修改方法

p = Path('/home/user/docs/report.txt')# 修改文件名
p.with_name('data.csv')      # /home/user/docs/data.csv# 修改主干名 (Python 3.9+)
p.with_stem('summary')       # /home/user/docs/summary.txt# 修改后缀
p.with_suffix('.pdf')        # /home/user/docs/report.pdf# 添加后缀
p.with_suffix(p.suffix + '.bak') # /home/user/docs/report.txt.bak

2.4 路径属性检查

p = Path('script.py')p.exists()       # 路径是否存在
p.is_file()      # 是否是文件
p.is_dir()       # 是否是目录
p.is_symlink()   # 是否是符号链接
p.is_block_device()  # 是否是块设备
p.is_char_device()   # 是否是字符设备
p.is_fifo()      # 是否是命名管道
p.is_socket()    # 是否是套接字
p.is_mount()     # 是否是挂载点 (Python 3.7+)
p.is_absolute()  # 是否是绝对路径
p.is_relative_to('/home')  # 是否相对于指定路径 (Python 3.9+)

3. 文件系统操作

3.1 文件读写

# 文本文件操作
content = Path('data.txt').read_text(encoding='utf-8')
Path('output.txt').write_text('Hello\nWorld', encoding='utf-8')# 二进制文件操作
data = Path('image.png').read_bytes()
Path('copy.png').write_bytes(data)# 追加内容
with Path('log.txt').open('a', encoding='utf-8') as f:f.write('\nNew log entry')

3.2 目录操作

# 创建目录
Path('new_dir').mkdir(exist_ok=True)
Path('nested/dirs').mkdir(parents=True, exist_ok=True)# 删除目录
Path('empty_dir').rmdir()  # 必须为空# 递归删除目录 (使用shutil)
import shutil
shutil.rmtree(Path('dir_to_remove'))

3.3 文件操作

# 创建文件
Path('new_file.txt').touch()# 重命名/移动文件
Path('old.txt').rename('new.txt')
Path('file.txt').replace('backup/file.txt')  # 原子性操作# 删除文件
Path('temp.txt').unlink(missing_ok=True)  # Python 3.8+# 创建符号链接
target = Path('target_file')
link = Path('link_file')
link.symlink_to(target)

3.4 文件属性操作

p = Path('file.txt')# 获取/设置权限
print(oct(p.stat().st_mode)[-3:])  # 权限八进制表示
p.chmod(0o644)  # 设置权限# 获取/设置时间戳
atime = p.stat().st_atime  # 访问时间
mtime = p.stat().st_mtime  # 修改时间
p.touch()  # 更新修改时间为当前时间# 更改所有者 (Unix-like系统)
import os
p.chown(1000, 1000)  # UID, GID

4. 目录遍历与模式匹配

4.1 目录遍历方法

# 遍历直接子项
for item in Path('.').iterdir():print(item.name)# 递归遍历
for item in Path('src').glob('**/*'):if item.is_file():print(item.relative_to('src'))

4.2 模式匹配技巧

# 查找所有Python文件
py_files = list(Path('.').glob('*.py'))# 递归查找所有测试文件
test_files = Path('tests').rglob('test_*.py')# 查找多个扩展名
code_files = Path('src').glob('*.[ch]')  # C头文件和源文件# 查找隐藏文件
dot_files = Path('.').glob('.*')# 使用生成器表达式筛选
large_files = (p for p in Path('.').iterdir() if p.is_file() and p.stat().st_size > 1e6)

4.3 高级文件查找

from datetime import datetime, timedelta# 按修改时间查找
cutoff = (datetime.now() - timedelta(days=7)).timestamp()
recent_files = [p for p in Path('logs').iterdir()if p.is_file() and p.stat().st_mtime > cutoff
]# 按文件内容查找
def find_in_files(directory, pattern):for p in Path(directory).rglob('*'):if p.is_file() and pattern in p.read_text():yield p

5. 高级路径处理

5.1 路径解析与规范化

# 解析符号链接
link_path = Path('symlink').resolve()# 相对路径计算
try:rel_path = Path('/a/b/c').relative_to('/a')print(rel_path)  # b/c
except ValueError:print("不是子路径")# 路径归一化
Path('a/./b/../c')  # 自动归一化为 a/c

5.2 临时文件处理

import tempfile# 创建临时目录
with tempfile.TemporaryDirectory() as tmpdir:tmp_path = Path(tmpdir)temp_file = tmp_path / 'temp.txt'temp_file.write_text('临时内容')# 使用临时文件...# 创建命名临时文件
with tempfile.NamedTemporaryFile(delete=False) as tmp:temp_path = Path(tmp.name)temp_path.write_text('保留内容')

5.3 路径模式匹配

from fnmatch import fnmatch# 自定义匹配函数
def complex_match(path, patterns):return any(fnmatch(path.name, pattern) for pattern in patterns)# 使用自定义匹配
files = [p for p in Path('.').iterdir() if complex_match(p, ['*.txt', '*.md'])]

6. 跨平台开发

6.1 处理路径差异

# 平台无关的路径创建
data_path = Path('data') / 'dataset.csv'# 处理Windows路径分隔符
win_path = Path('C:\\Users\\Name')
posix_path = Path('/home/name')# 转换路径风格
if os.name == 'nt':path_str = str(win_path)
else:path_str = str(posix_path)

6.2 纯路径计算

# 跨平台路径计算
server_path = PurePosixPath('/server/data')
local_path = PureWindowsPath('C:/local/data')# 路径相对关系
if server_path.is_relative_to('/server'):relative = server_path.relative_to('/server')

6.3 路径格式转换

# 转换为URI
from urllib.parse import urljoin
uri = urljoin('file:', Path('data.txt').absolute().as_uri())# 转换为字符串
str_path = str(Path('file.txt'))
bytes_path = bytes(Path('file.txt'))  # Python 3.10+

7. 性能优化

7.1 高效文件处理

# 处理大文件
with Path('large.log').open('r') as f:for line in f:process_line(line)# 使用内存映射
import mmap
with Path('huge.bin').open('rb') as f:with mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) as mm:process_memory(mm)

7.2 减少系统调用

# 避免重复stat调用
path = Path('file.txt')
stat_info = path.stat()
size = stat_info.st_size
mtime = stat_info.st_mtime# 批量文件操作
with ThreadPoolExecutor() as executor:executor.map(process_file, Path('.').glob('*.dat'))

7.3 高效目录遍历

# 使用生成器避免内存占用
def find_large_files(directory, min_size):for p in directory.rglob('*'):try:if p.is_file() and p.stat().st_size > min_size:yield pexcept OSError:  # 处理权限问题continue# 使用os.scandir底层API
def fast_dir_scan(path):with os.scandir(path) as entries:for entry in entries:yield Path(entry.path)

8. 与传统模块对比

8.1 与os/os.path对比

操作 os/os.path pathlib
路径拼接 os.path.join('a', 'b') Path('a') / 'b'
获取文件名 os.path.basename(p) Path(p).name
获取父目录 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).absolute()

8.2 与glob对比

操作 glob pathlib
简单匹配 glob.glob('*.py') list(Path().glob('*.py'))
递归匹配 glob.glob('**/*.py', recursive=True) list(Path().rglob('*.py'))
结果类型 字符串列表 Path对象列表

Pathlib优势

  • 面向对象接口
  • 方法链式调用
  • 统一API接口
  • 更好的异常处理
  • 自动路径归一化

9. 最佳实践

9.1 优先使用Path对象

# 推荐:使用Path对象操作
config = Path.home() / '.config' / 'app.ini'
if config.exists():settings = config.read_text()# 不推荐:混合字符串和Path
config = os.path.join(os.path.expanduser('~'), '.config', 'app.ini')

9.2 利用链式调用

# 方法链示例
(Path('data').with_suffix('.csv').read_text(encoding='utf-8').splitlines().filter(lambda x: 'error' in x))

9.3 安全路径操作

# 检查路径存在再操作
config_path = Path.home() / '.config' / 'myapp'
if config_path.exists():for cfg in config_path.glob('*.conf'):process_config(cfg)
else:create_default_config(config_path)

9.4 处理路径注入

# 验证用户输入路径
def safe_open(user_input):base = Path('/safe/directory')requested = base / user_inputif base.resolve() not in requested.resolve().parents:raise ValueError("非法路径访问")return requested.open()

9.5 跨平台开发技巧

# 使用Path处理路径分隔符
data_file = Path('data') / 'dataset.csv'# 避免硬编码分隔符
if Path('/') in Path.cwd().parents:print("Unix-like系统")

9.6 高效文件处理

# 使用上下文管理器
with Path('data.json').open('r', encoding='utf-8') as f:data = json.load(f)# 处理大文件
def process_large_file(path):with path.open('rb') as f:while chunk := f.read(8192):process_chunk(chunk)

10. 常见问题解决

10.1 路径不存在错误

try:content = Path('missing.txt').read_text()
except FileNotFoundError:create_file('missing.txt')

10.2 权限问题处理

try:Path('restricted.txt').write_text('content')
except PermissionError:print("无写入权限,尝试使用sudo")

10.3 符号链接处理

# 解析符号链接
actual_path = Path('symlink').resolve()# 创建相对符号链接
Path('link').symlink_to(Path('../target'))

10.4 处理非常规文件名

# 处理带空格或特殊字符的文件名
weird_file = Path('file with spaces.txt')
content = weird_file.read_text()# 处理非UTF-8文件名
import sys
for p in Path('.').iterdir():try:print(p.name)except UnicodeEncodeError:print(p.name.encode(sys.getfilesystemencoding(), errors='replace'))

10.5 路径注入防御

# 防止目录遍历攻击
def safe_join(base, user_path):base = Path(base).resolve()target = base / user_pathif base.resolve() not in target.resolve().parents:raise ValueError("非法路径")return target

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/908168.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

反省

我大抵是废了、累了。

US$34 Bluetooth Adapter for Yanhua Mini ACDP

Bluetooth Adapter for Yanhua Mini ACDPPackage List:1pc x Bluetooth Adapter for Yanhua Mini ACDP Pictures of Bluetooth Adapter for Yanhua Mini ACDPBluetooth Adapter for Yanhua Mini ACDP, now only need U…

global 设置内核源码在线浏览

global 设置内核源码在线浏览获取内核源码放到http家目录 /var/www/html/linux-5.10.0-136.12.0.86.x86_64 下载编译global wget https://ftp.gnu.org/gnu/global/global-6.6.tar.gz tar xf global-6.6.tar.gz cd glob…

[Nacos/Docker/MCP] Nacos 3.x : 为 AI MCP 而生

0 序言 : Nacos 3.x 的发布2025年4月28日,Nacos 3.0 正式发布:MCP Registry、安全零信任、链接更多生态升级 MCP Registry,围绕着 MCP 服务管理,MCP 多种类型注册,包含 MCP Server 注册、编排、动态调试和管理,…

牛客周赛 Round 108 CDEF题解

C、小苯的数字合并 题意: 小苯有一个长度为 $ n $ 的数组 $ a_1, a_2, \ldots, a_n $,他可以对 $ a $ 进行任意次“数字合并”操作,具体地,一次数字合并操作描述为:选择一个下标 $ i $ ($ 1 \leq i < |a| $),…

[LeetCode] 3484. Design Spreadsheet

A spreadsheet is a grid with 26 columns (labeled from A to Z) and a given number of rows. Each cell in the spreadsheet can hold an integer value between 0 and 105. Implement the Spreadsheet class: Spre…

Redis的使用问题

1:穿透,访问缓存中没有,数据库中也没有的数据,直接忽略缓存层,直达数据库 解决方案:方案一,查一个不存在的数据时,给一个设置一定过期间的key的数据,存入缓存,方案二:布隆过滤器,在将数据存入Redis时,会同…

AIGC拾遗:Flash Attention

前言 对于attention操作,其计算复杂度随着序列长度的增加呈平方倍的增长。因此,出现了诸多尝试将计算复杂度降低为\(O(n)\)的注意力机制。然而,这些方法忽略了计算时的IO复杂度的影响,频繁的内存交换也在长序列计算…

深度好文-风雨飘摇信竞路

风雨飘摇信竞路 写作时间:2025.9.19夜 1. 引子 夜深了,我捣鼓好了博客园,长舒了一口气。 明天就是 CSP-S 的初赛了,上周老师说可能这次我们没有初赛直升的名额了,把我们搞得都很慌,做了不少卷子。明天早上我还要…

Python-CSV库

CSV (Comma Separated Values) 是电子表格和数据库中最常见的数据交换格式。Python 的 csv 模块提供了读写 CSV 文件的功能,支持多种 CSV 变体和自定义格式。Python CSV 库 1. 库概述 1.1 简介 CSV (Comma Separated …

C++小白修仙记_LeetCode刷题_位运算

位运算 (难度:easy) 231. 2 的幂 给你一个整数 n,请你判断该整数是否是 2 的幂次方。如果是,返回 true ;否则,返回 false 。 如果存在一个整数 x 使得 n == 2x ,则认为 n 是 2 的幂次方。 示例: 输入:n = 1 …

C++小白修仙记_LeetCode刷题_双指针

双指针(easy) 345. 反转字符串中的元音字母 给你一个字符串 s ,仅反转字符串中的所有元音字母,并返回结果字符串。 元音字母包括 a、e、i、o、u,且可能以大小写两种形式出现不止一次。 示例: 输入:s = "Ic…

前路漫漫亦灿灿 往事堪堪亦澜澜

想了好久不知道从何下笔。 谨以本文慰藉我一段难忘的大学生生活,一个难忘的学期。 仍然忘不了军训时了解到ACM实验室,一切的一切从某位舍友,未来的集训队友、假期的守舍人、一个讨厌的人开始。从他那里的得知道了编…

设计模式(C++)详解—单例模式(2) - 指南

设计模式(C++)详解—单例模式(2) - 指南2025-09-19 22:51 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block …

使用uv和pycharm搭建python开发环境

uv是一个Rust编写的极速Python包和项目管理工具。官网: https://docs.astral.sh/uv/ , 中文的详细使用文档: https://uv.doczh.com/ 可以用来安装和管理个多版本python,创建管理不同的虚拟环境,所谓虚拟环境是将包…

lc1032-字符流

难度:困难题目描述设计一个算法:接收一个字符流,并检查每个新字符加进来形成的新串,其后缀是否是字符串数组 words 中的一个字符串示例 输入: ["StreamChecker", "query", "query"…

lc1032-字符流

难度:困难题目描述设计一个算法:接收一个字符流,并检查每个新字符加进来形成的新串,其后缀是否是字符串数组 words 中的一个字符串示例 输入: ["StreamChecker", "query", "query"…

八股整理xdsm - 教程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

C++小白修仙记_LeetCode刷题_哈希表

哈希表(难度:easy) 217. 存在重复元素 给你一个整数数组 nums 。如果任一值在数组中出现 至少两次 ,返回 true ;如果数组中每个元素互不相同,返回 false 。 示例: 输入:nums = [1,2,3,1] 输出:true 解释: 元…

【F#学习】字符串String

字符串 F#的字符串和其他现代化的语言的字符串差异不大。 let fruit = "Apple"字符串可以通过调用其本身的函数来修改,也可以通过String模块下的函数来修改——但字符串是常量,一旦被创建就不可能发生改变…