pin_drop当前位置:知识文库 ❯ 图文
Python标准库pathlib详解
目录
一、pathlib概述
pathlib 是Python 3.4引入的标准库,提供了一种面向对象的方式来处理文件系统路径。相比于传统的 os.path 模块,pathlib使用 Path 对象来表示路径,使得路径操作更加直观和优雅。
pathlib的核心类是 Path,它有两个主要子类:PurePath(纯路径操作,不访问文件系统)和 ConcretePath(具体路径,可以访问文件系统)。在日常开发中,我们主要使用 Path 类。
代码示例
from pathlib import Path
# 创建Path对象
current_dir = Path('.')
home_dir = Path.home()
desktop = Path.home() / 'Desktop'
print(f"当前目录: {current_dir.absolute()}")
print(f"用户主目录: {home_dir}")二、Path对象创建与基本操作
1. 创建Path对象
代码示例
from pathlib import Path
# 从字符串创建
p1 = Path('C:/Users/test/file.txt')
p2 = Path('C:', 'Users', 'test', 'file.txt')
# 从变量拼接
folder = 'documents'
filename = 'report.pdf'
p3 = Path('C:/Users/test') / folder / filename
print(p1)
print(p2)
print(p3)2. 路径属性获取
代码示例
from pathlib import Path
p = Path('C:/Users/test/documents/report.pdf')
print(f"完整路径: {p}")
print(f"驱动器: {p.drive}") # C:
print(f"根目录: {p.root}") # /
print(f"锚点: {p.anchor}") # C:/
print(f"父目录: {p.parent}") # C:/Users/test/documents
print(f"祖父目录: {p.parent.parent}") # C:/Users/test
print(f"文件名: {p.name}") # report.pdf
print(f"文件后缀: {p.suffix}") # .pdf
print(f"文件后缀(无点): {p.suffix[1:]}") # pdf
print(f"文件名(无后缀): {p.stem}") # report
print(f"所有后缀: {p.suffixes}") # ['.pdf']3. 路径判断与检查
代码示例
from pathlib import Path
# 创建测试文件
test_file = Path('test_example.txt')
test_file.write_text('Hello, pathlib!')
p = Path('test_example.txt')
print(f"是否存在: {p.exists()}") # True
print(f"是否为文件: {p.is_file()}") # True
print(f"是否为目录: {p.is_dir()}") # False
print(f"是否为绝对路径: {p.is_absolute()}") # False
print(f"文件大小(字节): {p.stat().st_size}")
# 清理测试文件
test_file.unlink()
print(f"删除后是否存在: {test_file.exists()}") # False三、路径拼接与解析
1. 使用 / 运算符拼接路径
代码示例
from pathlib import Path
base = Path('C:/projects')
# 使用 / 运算符拼接(推荐方式)
src = base / 'src'
module = src / 'main.py'
config = base / 'config' / 'settings.json'
print(src) # C:\projects\src
print(module) # C:\projects\src\main.py
print(config) # C:\projects\config\settings.json
# 可以连续拼接
full_path = Path('C:') / 'users' / 'test' / 'data.csv'
print(full_path)2. 路径解析方法
代码示例
from pathlib import Path
# resolve(): 解析为绝对路径,解决 .. 和 .
p = Path('./docs/../src/./main.py')
print(f"原始路径: {p}")
print(f"解析后: {p.resolve()}")
# with_name(): 替换文件名
p = Path('C:/data/report_v1.csv')
new_file = p.with_name('report_v2.csv')
print(new_file) # C:\data\report_v2.csv
# with_suffix(): 替换文件后缀
py_file = Path('script.py')
txt_file = py_file.with_suffix('.txt')
print(txt_file) # script.txt
# relative_to(): 计算相对路径
base = Path('C:/projects/myapp')
full = Path('C:/projects/myapp/src/utils/helper.py')
relative = full.relative_to(base)
print(relative) # src\utils\helper.py四、文件读写操作
1. 文本文件读写
代码示例
from pathlib import Path
# 创建文件并写入文本
file_path = Path('sample.txt')
file_path.write_text('Hello, pathlib!\n这是第二行\n这是第三行')
print(f"文件已创建: {file_path}")
# 读取全部文本
content = file_path.read_text()
print(f"全部内容:\n{content}")
# 按行读取
lines = file_path.read_text().splitlines()
print(f"行数: {len(lines)}")
for i, line in enumerate(lines, 1):
print(f"第{i}行: {line}")
# 追加文本
with file_path.open('a', encoding='utf-8') as f:
f.write('\n这是追加的内容\n')
# 读取字节
# bytes_content = Path('image.png').read_bytes()2. 使用open()上下文管理器
代码示例
from pathlib import Path
import json
# 写入JSON文件
data = {
'name': 'Python教程',
'version': '3.11',
'topics': ['pathlib', 'os.path', '文件操作']
}
json_path = Path('config.json')
with json_path.open('w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
print(f"JSON文件已保存: {json_path}")
# 读取JSON文件
with json_path.open('r', encoding='utf-8') as f:
loaded_data = json.load(f)
print(f"读取的数据: {loaded_data}")
# 清理
json_path.unlink()
Path('sample.txt').unlink()五、目录遍历与文件匹配
1. 列出目录内容
代码示例
from pathlib import Path
# 创建测试目录结构
test_dir = Path('test_project')
test_dir.mkdir(exist_ok=True)
(test_dir / 'src').mkdir(exist_ok=True)
(test_dir / 'docs').mkdir(exist_ok=True)
(test_dir / 'src' / 'main.py').touch()
(test_dir / 'src' / 'utils.py').touch()
(test_dir / 'docs' / 'readme.md').touch()
(test_dir / 'config.json').touch()
# iterdir(): 列出目录内容
print("目录内容:")
for item in test_dir.iterdir():
type_str = "目录" if item.is_dir() else "文件"
print(f" [{type_str}] {item.name}")
# 列表推导式
files_only = [f.name for f in test_dir.iterdir() if f.is_file()]
dirs_only = [d.name for d in test_dir.iterdir() if d.is_dir()]
print(f"\n文件: {files_only}")
print(f"目录: {dirs_only}")2. glob模式匹配
代码示例
from pathlib import Path
test_dir = Path('test_project')
# glob(): 查找匹配的文件
print("所有Python文件:")
for f in test_dir.glob('**/*.py'):
print(f" {f}")
print("\n所有Markdown文件:")
for f in test_dir.glob('**/*.md'):
print(f" {f}")
print("\n所有JSON文件:")
for f in test_dir.glob('**/*.json'):
print(f" {f}")
# rglob(): 递归匹配(等价于 **/*)
print("\n递归查找所有.txt文件:")
for f in test_dir.rglob('*.txt'):
print(f" {f}")
# 清理测试目录
import shutil
shutil.rmtree(test_dir)3. walk()递归遍历
代码示例
from pathlib import Path
# Python 3.12+ Path支持walk()方法
# 兼容旧版本的替代方案:
def walk_directory(path):
"""递归遍历目录"""
p = Path(path)
for item in sorted(p.rglob('*')):
indent = ' ' * len(item.relative_to(p).parts) - 1
prefix = '|-- ' if item.is_file() else '|-- [D] '
print(f"{indent}{prefix}{item.name}")
# 创建示例结构
demo = Path('demo_folder')
demo.mkdir(exist_ok=True)
(demo / 'level1').mkdir()
(demo / 'level1' / 'level2').mkdir()
(demo / 'file1.txt').touch()
(demo / 'level1' / 'file2.py').touch()
(demo / 'level1' / 'level2' / 'file3.md').touch()
print("目录树结构:")
print(f"[D] {demo.name}")
for item in sorted(demo.rglob('*')):
depth = len(item.relative_to(demo).parts)
indent = ' ' * (depth - 1)
prefix = '|-- '
if item.is_dir():
print(f"{indent}{prefix}[D] {item.name}")
else:
print(f"{indent}{prefix}{item.name}")
# 清理
import shutil
shutil.rmtree(demo)六、pathlib与os.path对比
七、注意事项与最佳实践
1. 路径字符串 vs Path对象
注意:虽然Path对象可以自动转换为字符串,但某些旧API(如
open()在Python 3.5之前)可能不直接接受Path对象。此时需要使用str(path)显式转换。Python 3.6+的内置open()已经原生支持Path对象。
2. 跨平台兼容性
提示:pathlib会自动处理不同操作系统的路径分隔符。在Windows上使用反斜杠
\,在Linux/macOS上使用正斜杠/。建议在代码中统一使用正斜杠,pathlib会自动转换。
代码示例
from pathlib import Path
# 推荐使用正斜杠(跨平台兼容)
p = Path('folder/subfolder/file.txt')
# 在Windows上打印时会自动显示为反斜杠
print(p) # Windows: folder\subfolder\file.txt
# Linux: folder/subfolder/file.txt3. 安全删除文件
注意:删除文件前务必检查文件是否存在,避免抛出
FileNotFoundError。可以使用missing_ok=True参数(Python 3.8+)来安全删除。
代码示例
from pathlib import Path
# 安全删除文件
file_path = Path('some_file.txt')
# 方法1:先检查再删除
if file_path.exists():
file_path.unlink()
print("文件已删除")
# 方法2:使用missing_ok(Python 3.8+)
file_path.unlink(missing_ok=True)
print("安全删除完成(不存在也不报错)")4. 批量重命名文件
代码示例
from pathlib import Path
# 创建测试文件
demo_dir = Path('rename_demo')
demo_dir.mkdir(exist_ok=True)
for i in range(5):
(demo_dir / f'photo_{i:02d}.jpg').touch()
# 批量重命名
print("重命名前:")
for f in demo_dir.iterdir():
print(f" {f.name}")
for file_path in demo_dir.iterdir():
if file_path.suffix == '.jpg':
new_name = file_path.stem.replace('photo', 'image') + '.jpeg'
new_path = file_path.with_name(new_name).with_suffix('.jpeg')
file_path.rename(new_path)
print("\n重命名后:")
for f in demo_dir.iterdir():
print(f" {f.name}")
# 清理
import shutil
shutil.rmtree(demo_dir)小贴士
Python官方推荐在新代码中优先使用pathlib而非os.path。pathlib的面向对象设计使代码更简洁易读,特别是在处理复杂路径操作时。如果你的项目需要兼容Python 3.4以下版本,才需要考虑使用os.path。更多关于pathlib的详细信息,可以参考Python官方文档。
八、课程小结
-
Path对象:使用Path类表示路径,支持直观的面向对象操作,如属性获取、拼接、解析等
-
路径拼接:使用 / 运算符替代os.path.join,代码更简洁直观
-
文件读写:read_text()、write_text()、read_bytes()、write_bytes()方法简化文件I/O操作
-
目录遍历:iterdir()、glob()、rglob()方法提供强大的目录遍历和文件匹配功能
-
跨平台兼容:自动处理不同操作系统的路径分隔符,编写一次代码,多处运行
常见问题
pathlib和os.path应该用哪个?
Python官方推荐在新项目中优先使用pathlib。pathlib的面向对象设计使代码更简洁、可读性更好。只有在需要兼容Python 3.4以下版本,或者与只接受字符串路径的第三方库交互时,才考虑使用os.path。
Path对象可以直接传给open()函数吗?
在Python 3.6+中,内置的open()函数原生支持Path对象,可以直接传入。如果你使用的是Python 3.5或更早版本,则需要使用str(path)将Path对象转换为字符串。
glob()和rglob()有什么区别?
glob()只匹配当前目录或指定模式的文件,需要使用 **/* 前缀才能递归;rglob()本身就是递归匹配,等价于glob('**/pattern')。例如 Path('.').rglob('*.py') 等价于 Path('.').glob('**/*.py')。
如何判断两个Path对象是否指向同一个文件?
可以使用 resolve() 方法将两个路径都解析为绝对路径后再比较。例如:path1.resolve() == path2.resolve()。resolve() 会解析符号链接、去除 . 和 .. 等相对路径元素,确保比较的是实际的文件位置。
练习1
使用pathlib编写程序,扫描指定目录,统计各种文件类型(按后缀分类)的数量,并输出一个类似"图片文件(.jpg, .png): 15个"、"文档文件(.pdf, .docx): 8个"的分类统计报告。
练习2
编写一个函数,接收一个目录路径作为参数,使用pathlib递归查找该目录下所有超过指定大小(如1MB)的文件,并按照文件大小从大到小排序输出。该工具可用于查找磁盘中的大文件。
本文涉及AI创作
内容由AI创作,请仔细甄别