使用pathlib优化你的路径操作

1. pathlib 是什么?

在日常的 Python 编程中,文件和目录的路径处理是一个常见且重要的任务。许多开发者习惯使用 os 模块来完成这些操作,例如获取文件列表、检查文件是否存在等。然而,直接将路径作为字符串进行处理可能会导致代码冗长、复杂,且容易出错。

自 Python 3.4 起,官方引入了 pathlib 模块,提供了一种更加优雅和高效的方式来处理文件系统路径。pathlib 通过将路径表示为对象,支持面向对象的路径操作,使代码更加简洁、可读。

本文将深入探讨 pathlib 模块的强大功能,通过实例对比展示其相对于 os 模块的优势,帮助你在文件和目录操作中事半功倍。

1.1 os 的局限性

假设我们需要获取某个目录下的所有 .txt 文件,使用 os 模块时,可能需要编写如下代码:

import os

directory = "/Users/yourname/Documents"
txt_files = [
    os.path.join(directory, f)
    for f in os.listdir(directory)
    if os.path.isfile(os.path.join(directory, f)) and f.endswith(".txt")
]

这段代码中,我们需要多次调用 os.path 的方法来拼接路径和检查文件类型,代码显得繁琐且不直观。

1.2 pathlib 的优势

使用 pathlib,上述操作可以简化为:

from pathlib import Path

directory = Path("/Users/yourname/Documents")
txt_files = list(directory.glob("*.txt"))

pathlib 将文件系统路径视为对象,提供了丰富的方法来操作路径,使代码更加简洁清晰。许多大型开源项目都在使用 pathlib,足以证明其强大之处。

2. 路径操作详解

pathlib 模块的核心是 Path 类,它为文件和目录的操作提供了面向对象的接口。

2.1 路径对象创建

获取当前目录:

from pathlib import Path

current_dir = Path.cwd()
print(current_dir)
# 输出示例:/Users/yourname/Projects

获取用户主目录:

home_dir = Path.home()
print(home_dir)
# 输出示例:/Users/yourname

通过字符串定义路径:

p = Path("my_folder")
print(p)
# 输出:my_folder

/ 运算符连接路径:

data_folder = Path(".") / "data"
csv_file = data_folder / "dataset.csv"

print(data_folder)
# 输出:data

print(csv_file)
# 输出:data/dataset.csv

使用 / 运算符可以直观地拼接路径,而不需要调用 os.path.join

2.2 路径属性检查

判断路径是否存在:

data_folder.exists()
# 返回 True 或 False

判断是否为目录或文件:

data_folder.is_dir()
# 返回 True 或 False

csv_file.is_file()
# 返回 True 或 False

获取绝对路径:

absolute_path = csv_file.resolve()
print(absolute_path)
# 输出示例:/Users/yourname/Projects/data/dataset.csv

转换路径为字符串:

path_str = str(Path.home())
print(path_str)
# 输出:/Users/yourname

值得注意的是,现代的许多库(如 pandasmatplotlibseaborn 等)都支持 Path 对象作为参数,进一步提升了 pathlib 的实用性。

3. Path 对象的属性和方法

Path 对象拥有许多有用的属性和方法,方便我们获取路径的各种信息。

3.1 获取路径的组成部分

访问父级目录:

image_file = Path("images/sample.png").resolve()
print(image_file.parent)
# 输出示例:/Users/yourname/Projects/images

获取文件名称:

print(image_file.name)
# 输出:sample.png

获取文件的前缀和后缀:

print(image_file.stem)
# 输出:sample

print(image_file.suffix)
# 输出:.png

分解路径为各个部分:

print(image_file.parts)
# 输出:('/', 'Users', 'yourname', 'Projects', 'images', 'sample.png')

列出所有父级目录:

for parent in image_file.parents:
    print(parent)

输出:

/Users/yourname/Projects/images
/Users/yourname/Projects
/Users/yourname
/Users
/

3.2 修改路径信息

更改文件名或扩展名:

new_image_file = image_file.with_name("updated_sample.jpg")
print(new_image_file)
# 输出示例:/Users/yourname/Projects/images/updated_sample.jpg

修改文件后缀:

jpg_file = image_file.with_suffix(".jpg")
print(jpg_file)
# 输出示例:/Users/yourname/Projects/images/sample.jpg

4. 文件操作

pathlib 不仅可以处理路径,还提供了方便的方法来操作文件。

4.1 文件的读写

写入文本或二进制数据:

markdown_file = data_folder / "notes.md"

# 写入文本内容(会覆盖原有内容)
markdown_file.write_text("# 这是一个示例 Markdown 文件")

# 写入二进制内容
binary_file = data_folder / "data.bin"
binary_file.write_bytes(b'\x10\x20\x30\x40')

读取文本或二进制数据:

content = markdown_file.read_text()
print(content)
# 输出:# 这是一个示例 Markdown 文件

binary_content = binary_file.read_bytes()
print(binary_content)
# 输出:b'\x10\x20\x30\x40'

向文件追加内容:

with markdown_file.open(mode="a") as file:
    file.write("\n## 追加的新章节")

print(markdown_file.read_text())
# 输出:
# # 这是一个示例 Markdown 文件
# ## 追加的新章节

4.2 文件的重命名与删除

重命名文件:

renamed_file = markdown_file.with_stem("renamed_notes")
markdown_file.rename(renamed_file)
# 文件已重命名为 data/renamed_notes.md

获取文件大小:

file_size = renamed_file.stat().st_size
print(file_size)
# 输出文件大小(字节数)

获取文件的修改时间:

from datetime import datetime

mod_time = datetime.fromtimestamp(renamed_file.stat().st_mtime)
print(mod_time)
# 输出示例:2023-08-15 14:20:30.123456

删除文件:

renamed_file.unlink(missing_ok=True)
# 文件已被删除

missing_ok=True 表示如果文件不存在,不会引发异常。

5. 目录处理

pathlib 同样提供了丰富的方法来创建、遍历和删除目录。

5.1 创建与移除目录

新建目录:

new_directory = Path("data/new_folder")
new_directory.mkdir(parents=True, exist_ok=True)
  • parents=True:如果父目录不存在,自动创建。
  • exist_ok=True:如果目录已存在,不会引发异常。

删除目录:

new_directory.rmdir()
# 注意:只能删除空目录

5.2 遍历目录内容

列举目录中的内容:

for item in Path.home().iterdir():
    print(item)

输出示例:

/Users/yourname/Documents
/Users/yourname/Downloads
/Users/yourname/Pictures
...

使用 glob 查找匹配模式的文件:

# 查找主目录下的所有 .txt 文件
home = Path.home()
text_files = list(home.glob("*.txt"))

print(len(text_files))
# 输出:找到的 .txt 文件数量

使用 rglob 进行递归搜索:

# 递归查找所有子目录中的 .txt 文件
all_text_files = list(home.rglob("*.txt"))

print(len(all_text_files))
# 输出:递归找到的 .txt 文件数量

6. Path 类的核心功能概览

本节对之前的内容进行了总结,方便大家速查。

实例化路径对象:

from pathlib import Path

# 当前目录
current_path = Path()

# 指定路径
specific_path = Path('/usr/local/bin')

路径操作方法:

  • 拼接路径path / 'subdir' / 'file.txt'
  • 获取绝对路径path.resolve()
  • 检查路径是否存在path.exists()
  • 判断是否为目录或文件path.is_dir()path.is_file()
  • 创建目录path.mkdir(parents=True, exist_ok=True)

访问路径信息:

  • 获取文件名path.name
  • 获取文件前缀path.stem
  • 获取文件后缀path.suffix
  • 获取父目录path.parent

文件读写操作:

  • 读取文本内容path.read_text()
  • 写入文本内容path.write_text("内容")
  • 读取二进制内容path.read_bytes()
  • 写入二进制内容path.write_bytes(b'数据')

遍历目录内容:

  • 遍历当前目录下的文件path.glob('*')
  • 递归遍历所有子目录path.rglob('*')

Ref

[1] https://www.bilibili.com/read/cv25592439/
[2] https://github.com/chris1610/pbpython/blob/master/extras/Pathlib-Cheatsheet.pdf
[3] https://docs.python.org/zh-cn/3/library/pathlib.html

猜你喜欢

转载自blog.csdn.net/raelum/article/details/142353605