python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python  pathlib模块使用

Python  pathlib模块使用实例教程

作者:70asunflower

本文介绍了pathlib模块,作为os.path的升级,提供了面向对象的文件路径处理方式,文章主要介绍了pathlib的基本用法,结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧

pathlib 是 Python 3.4+ 引入的面向对象的文件路径处理模块,比 os.path 更现代、更直观。它提供了 Path 类来表示文件系统路径。

1. 基本导入和初始化

from pathlib import Path
# 创建路径对象
p1 = Path()  # 当前目录
print(p1)  # .
p2 = Path('documents')  # 相对路径
print(p2)  # documents
p3 = Path('/home/user/file.txt')  # 绝对路径
print(p3)  # /home/user/file.txt
# 支持多级路径拼接(不需要 join)
p4 = Path('home') / 'user' / 'docs' / 'readme.md'
print(p4)  # home/user/docs/readme.md

2. 路径拼接与拆分

2.1 使用/运算符拼接

# 使用斜杠拼接(跨平台)
root = Path('/home/user')
full_path = root / 'documents' / 'notes.txt'
print(full_path)  # /home/user/documents/notes.txt
# 也可以使用 joinpath()
path = Path('/tmp')
full = path.joinpath('data', 'logs', 'app.log')
print(full)  # /tmp/data/logs/app.log
# 支持字符串和Path对象混用
base = Path('/var')
new = base / 'www' / 'html'
print(new)  # /var/www/html

2.2 获取路径各部分

path = Path('/home/user/documents/file.tar.gz')
# 获取文件名(包含所有扩展名)
print(path.name)  # file.tar.gz
# 获取不带扩展名的文件名
print(path.stem)  # file.tar
# 获取扩展名(最后一个点之后)
print(path.suffix)  # .gz
# 获取所有扩展名(Python 3.12+)
print(path.suffixes)  # ['.tar', '.gz']
# 获取父目录
print(path.parent)  # /home/user/documents
print(path.parent.parent)  # /home/user
# 获取所有祖先
for parent in path.parents:
    print(parent)
    # /home/user/documents
    # /home/user
    # /home
    # /
# 获取根目录
print(path.anchor)  # /

2.3 拆分组装示例

# 实际应用:替换文件扩展名
file = Path('report.xlsx')
new_file = file.with_suffix('.pdf')
print(new_file)  # report.pdf
# 修改文件名
old = Path('data/old_name.txt')
new = old.with_name('new_name.txt')
print(new)  # data/new_name.txt
# 组合使用
config = Path('/etc/nginx/nginx.conf')
backup = config.with_name(config.stem + '.backup' + config.suffix)
print(backup)  # /etc/nginx/nginx.backup.conf

3. 路径检查与属性

# 假设当前目录有 test.txt 文件和 mydir 目录
path_file = Path('test.txt')
path_dir = Path('mydir')
path_link = Path('symlink')  # 假设存在符号链接
# 存在性检查
print(path_file.exists())    # True
print(Path('nonexist').exists())  # False
# 类型检查
print(path_file.is_file())   # True
print(path_dir.is_file())    # False
print(path_file.is_dir())    # False
print(path_dir.is_dir())     # True
# 其他检查
print(path_file.is_absolute())  # False
print(Path('/home/file.txt').is_absolute())  # True
print(path_file.is_symlink())   # False
print(path_link.is_symlink())   # True
# 路径比较(自动跨平台)
p1 = Path('/home/user')
p2 = Path('/home') / 'user'
print(p1 == p2)  # True

4. 目录操作

4.1 创建和删除目录

# 创建单级目录
new_dir = Path('new_folder')
new_dir.mkdir(exist_ok=True)  # exist_ok=True 避免已存在时报错
print(new_dir.exists())  # True
# 创建多级目录
nested = Path('parent/child/grandchild')
nested.mkdir(parents=True, exist_ok=True)
print(nested.exists())  # True
# 删除目录(必须为空)
empty_dir = Path('temp_empty')
empty_dir.mkdir()
empty_dir.rmdir()  # 删除空目录
# 删除目录及内容(Python 3.12+)
# import shutil
# shutil.rmtree('parent')  # 递归删除

4.2 列出目录内容

# 列出所有内容
docs = Path('/home/user/documents')
for item in docs.iterdir():
    print(item.name)
    # 输出示例:
    # report.pdf
    # images
    # notes.txt
    # backup
# 使用 glob 模式匹配
# 查找所有 .txt 文件
for txt_file in docs.glob('*.txt'):
    print(txt_file)
    # /home/user/documents/notes.txt
    # /home/user/documents/readme.txt
# 递归查找(** 表示任意子目录)
for py_file in docs.glob('**/*.py'):
    print(py_file)
    # /home/user/documents/scripts/main.py
    # /home/user/documents/tools/helper.py
# 区分文件和目录
for item in docs.iterdir():
    if item.is_file():
        print(f"文件: {item.name}")
    elif item.is_dir():
        print(f"目录: {item.name}")

5. 文件操作

5.1 读写文件

# 写文件
file_path = Path('example.txt')
# 方法1:write_text
file_path.write_text('Hello, World!', encoding='utf-8')
print(file_path.read_text(encoding='utf-8'))  # Hello, World!
# 方法2:write_bytes(二进制)
bin_path = Path('data.bin')
bin_path.write_bytes(b'\x00\x01\x02\x03')
print(bin_path.read_bytes())  # b'\x00\x01\x02\x03'
# 方法3:使用 open() 方法(上下文管理)
with file_path.open('a', encoding='utf-8') as f:
    f.write('\nAppended line')
print(file_path.read_text(encoding='utf-8'))
# Hello, World!
# Appended line
# 删除文件
file_path.unlink(missing_ok=True)  # missing_ok=True 不报错

5.2 复制和移动文件

from pathlib import Path
import shutil
# 复制文件
src = Path('source.txt')
dst = Path('backup/source_copy.txt')
# 创建目标目录(如果需要)
dst.parent.mkdir(parents=True, exist_ok=True)
# 复制
shutil.copy2(src, dst)  # 保留元数据
print(dst.exists())  # True
# 移动/重命名文件
old = Path('old_name.txt')
new = Path('new_name.txt')
old.rename(new)  # 重命名
print(new.exists())  # True
print(old.exists())  # False
# 移动文件到其他目录
src = Path('data.txt')
dst = Path('archive/data.txt')
src.rename(dst)
print(dst.exists())  # True

6. 文件属性和信息

path = Path('test.txt')
# 文件大小(字节)
print(path.stat().st_size)  # 1024
# 获取文件信息
stat = path.stat()
print(f"大小: {stat.st_size} 字节")          # 大小: 1024 字节
print(f"权限: {oct(stat.st_mode)}")         # 权限: 0o100644
print(f"最后访问: {stat.st_atime}")         # 最后访问: 1747556123.45
print(f"最后修改: {stat.st_mtime}")         # 最后修改: 1747556100.00
# 使用 datetime 格式化时间
from datetime import datetime
mtime = datetime.fromtimestamp(stat.st_mtime)
print(f"修改时间: {mtime}")  # 修改时间: 2026-05-18 10:15:00
# 获取绝对路径
print(path.absolute())  # /home/user/project/test.txt
print(path.resolve())   # 解析符号链接后的绝对路径
# 获取相对路径
current = Path.cwd()
abs_path = Path('/home/user/project/test.txt')
rel_path = abs_path.relative_to(current)
print(rel_path)  # test.txt

7. 实战示例

7.1 批量重命名文件

def batch_rename(directory, old_ext, new_ext):
    """批量修改文件扩展名"""
    dir_path = Path(directory)
    for file_path in dir_path.glob(f'*.{old_ext}'):
        new_path = file_path.with_suffix(f'.{new_ext}')
        file_path.rename(new_path)
        print(f"重命名: {file_path.name} -> {new_path.name}")
        # 重命名: image.jpg -> image.png
        # 重命名: doc.jpg -> doc.png
# 使用示例
# batch_rename('./images', 'jpg', 'png')

7.2 递归统计文件类型

from collections import Counter
def count_file_types(directory):
    """递归统计目录中各类型文件数量"""
    dir_path = Path(directory)
    type_counter = Counter()
    for file_path in dir_path.rglob('*'):
        if file_path.is_file():
            suffix = file_path.suffix or '无扩展名'
            type_counter[suffix] += 1
    return type_counter
# 使用示例
stats = count_file_types('/home/user/project')
for ext, count in stats.most_common(5):
    print(f"{ext:10} : {count} 个")
    # .py        : 42 个
    # .txt       : 15 个
    # .md        : 8 个
    # .json      : 5 个
    # 无扩展名    : 3 个

7.3 整理文件到日期目录

from datetime import datetime
import shutil
def organize_by_date(directory):
    """按文件修改日期整理文件到子目录"""
    base_path = Path(directory)
    for file_path in base_path.iterdir():
        if not file_path.is_file():
            continue
        # 获取修改日期
        mtime = datetime.fromtimestamp(file_path.stat().st_mtime)
        date_dir = base_path / mtime.strftime('%Y/%m')
        # 创建日期目录
        date_dir.mkdir(parents=True, exist_ok=True)
        # 移动文件
        dest = date_dir / file_path.name
        shutil.move(str(file_path), str(dest))
        print(f"移动: {file_path.name} -> {dest}")
        # 移动: report.pdf -> ./2026/05/report.pdf
# 使用示例
# organize_by_date('./downloads')

7.4 查找和清理空文件夹

def find_empty_dirs(directory):
    """递归查找所有空文件夹"""
    base_path = Path(directory)
    empty_dirs = []
    # rglob 查找所有目录,sort 确保先处理深层目录
    for dir_path in sorted(base_path.rglob('*'), reverse=True):
        if dir_path.is_dir():
            try:
                next(dir_path.iterdir())  # 尝试获取第一个子项
            except StopIteration:
                empty_dirs.append(dir_path)
    return empty_dirs
def clean_empty_dirs(directory, dry_run=True):
    """清理空文件夹"""
    empty_dirs = find_empty_dirs(directory)
    for dir_path in empty_dirs:
        if dry_run:
            print(f"[模拟] 将删除: {dir_path}")
            # [模拟] 将删除: /tmp/parent/empty
        else:
            dir_path.rmdir()
            print(f"已删除: {dir_path}")
            # 已删除: /tmp/parent/empty
# 使用示例
# clean_empty_dirs('./data', dry_run=True)  # 先预览
# clean_empty_dirs('./data', dry_run=False) # 实际删除

7.5 目录树展示

def display_tree(directory, prefix='', level=0, max_level=3):
    """以树形结构显示目录内容"""
    if level > max_level:
        return
    path = Path(directory)
    items = sorted(path.iterdir(), key=lambda x: (not x.is_dir(), x.name))
    for i, item in enumerate(items):
        is_last = (i == len(items) - 1)
        connector = '└── ' if is_last else '├── '
        print(f"{prefix}{connector}{item.name}{'/' if item.is_dir() else ''}")
        if item.is_dir():
            extension = '    ' if is_last else '│   '
            display_tree(item, prefix + extension, level + 1, max_level)
# 使用示例
print("项目目录结构:")
display_tree('/home/user/project', max_level=2)
# 项目目录结构:
# ├── docs/
# │   ├── readme.md
# │   └── api/
# │       └── index.html
# ├── src/
# │   ├── main.py
# │   └── utils.py
# └── tests/
#     └── test_main.py

8. Path 对象属性速查表

属性/方法说明示例
.name文件名(含扩展名)'file.tar.gz'
.stem文件名(不含扩展名)'file.tar'
.suffix最后一个扩展名'.gz'
.suffixes所有扩展名列表['.tar', '.gz']
.parent父目录'/home/user'
.parents所有祖先(可索引)[Path('/home'), Path('/')]
.anchor根目录部分'/''C:\\'
.absolute()绝对路径'/home/user/file.txt'
.resolve()解析后的绝对路径'/home/user/file.txt'
.exists()是否存在True
.is_file()是否为文件True
.is_dir()是否为目录False
.is_absolute()是否绝对路径True
.is_symlink()是否符号链接False
.stat()文件状态信息os.stat_result
.glob(pattern)匹配模式(非递归)生成器
.rglob(pattern)递归匹配生成器
.iterdir()遍历目录生成器
.mkdir()创建目录-
.rmdir()删除空目录-
.unlink()删除文件-
.rename(target)重命名/移动-
.read_text()读取文本'content'
.write_text()写入文本-
.read_bytes()读取二进制b'\x00\x01'
.write_bytes()写入二进制-
.with_name(name)替换文件名'/home/new.txt'
.with_suffix(suffix)替换扩展名'/home/file.pdf'

9. pathlib vs os.path 对比

# os.path 风格
import os.path
folder = 'data'
filename = 'file.txt'
path = os.path.join(folder, filename)
dirname = os.path.dirname(path)
basename = os.path.basename(path)
exists = os.path.exists(path)
size = os.path.getsize(path)
# pathlib 风格(更清晰)
from pathlib import Path
path = Path('data') / 'file.txt'
dirname = path.parent
basename = path.name
exists = path.exists()
size = path.stat().st_size

10. 最佳实践

# ✅ 推荐:使用 Path 对象
from pathlib import Path
# 获取当前文件所在目录
current_dir = Path(__file__).parent
# 项目根目录(假设在项目根目录执行)
project_root = Path.cwd()
# 构建数据路径
data_path = project_root / 'data' / 'raw_data.csv'
# 检查并创建目录
data_path.parent.mkdir(parents=True, exist_ok=True)
# 处理文件
if data_path.exists() and data_path.is_file():
    content = data_path.read_text(encoding='utf-8')
    # 处理内容...
# 遍历文件
for log_file in project_root.glob('logs/**/*.log'):
    if log_file.stat().st_size > 10 * 1024 * 1024:  # 大于10MB
        archive = log_file.with_suffix('.log.gz')
        print(f"归档大文件: {log_file} -> {archive}")

pathlib 提供了面向对象的、直观的路径操作方式,强烈推荐在新项目中使用它代替 os.path

到此这篇关于Python pathlib模块使用实例教程的文章就介绍到这了,更多相关Python pathlib模块使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文