01 - 文件与路径操作¶
学习时间: 1.5小时 重要性: ⭐⭐⭐⭐⭐ 每个项目都会用到
🎯 学习目标¶
- 掌握
pathlib的核心用法 - 了解
os和shutil的常用功能 - 能处理文件和目录的各种操作
📂 pathlib - 现代化的路径操作¶
基本概念¶
Python
from pathlib import Path
# 创建路径对象
path = Path("data/example.txt") # Path()提供面向对象的文件路径操作
# 路径拼接(使用 / 运算符)
path = Path("data") / "subdir" / "file.txt"
# 等价于
path = Path("data").joinpath("subdir", "file.txt")
# 获取当前目录和家目录
cwd = Path.cwd() # 当前工作目录
home = Path.home() # 用户主目录
路径信息¶
Python
path = Path("data/projects/example.py")
# 基本信息
print(path.name) # "example.py" - 文件名(含扩展名)
print(path.stem) # "example" - 文件名(不含扩展名)
print(path.suffix) # ".py" - 扩展名
print(path.parent) # "data/projects" - 父目录
print(path.parents[0]) # "data/projects"
print(path.parents[1]) # "data"
print(path.root) # "\" (Windows) 或 "/" (Unix)
# 存在性检查
print(path.exists()) # True/False - 是否存在
print(path.is_file()) # True/False - 是否是文件
print(path.is_dir()) # True/False - 是否是目录
# 绝对路径和相对路径
print(path.absolute()) # 获取绝对路径
print(path.resolve()) # 解析符号链接,获取绝对路径
文件读写¶
Python
from pathlib import Path
# 写入文件
Path("output.txt").write_text("Hello, World!", encoding="utf-8")
# 读取文件
content = Path("output.txt").read_text(encoding="utf-8")
# 二进制读写
Path("image.jpg").write_bytes(image_data)
data = Path("image.jpg").read_bytes()
# 实用示例:保存配置
config = {
"name": "MyApp",
"version": "1.0",
"debug": True
}
import json
config_path = Path("config.json")
config_path.write_text(json.dumps(config, ensure_ascii=False, indent=2))
目录操作¶
Python
from pathlib import Path
# 创建目录
Path("data/subdir").mkdir(parents=True, exist_ok=True)
# parents=True: 创建父目录(如果不存在)
# exist_ok=True: 目录已存在不报错
# 遍历目录
path = Path("data")
for item in path.iterdir():
print(f"{'目录' if item.is_dir() else '文件':<4} {item.name}")
# 递归遍历(查找所有Python文件)
for py_file in Path(".").rglob("*.py"):
print(py_file)
# 非递归遍历(只查找当前目录)
for txt_file in Path(".").glob("*.txt"):
print(txt_file)
# 统计目录中的文件数
py_count = len(list(Path("project").rglob("*.py")))
print(f"项目中有 {py_count} 个Python文件")
文件操作¶
Python
from pathlib import Path
# 复制、移动、重命名
Path("source.txt").rename("new_name.txt") # 重命名/移动
Path("source.txt").replace("destination.txt") # 移动(覆盖)
# 创建空文件
Path("new_file.txt").touch()
# 删除
Path("temp.txt").unlink() # 删除文件
Path("temp_dir").rmdir() # 删除空目录
# 检查文件权限
print(Path("file.txt").stat()) # 获取文件状态信息
print(Path("file.txt").stat().st_size) # 文件大小(字节)
print(Path("file.txt").stat().st_mtime) # 修改时间(时间戳)
# 实用示例:清理临时文件
def clean_temp_files(directory, pattern="*.tmp"):
"""删除目录下所有匹配pattern的临时文件"""
path = Path(directory)
for temp_file in path.glob(pattern):
temp_file.unlink()
print(f"已删除: {temp_file}")
clean_temp_files("./temp")
🔧 shutil - 高级文件操作¶
Python
import shutil
from pathlib import Path
# 复制文件
shutil.copy("source.txt", "destination.txt") # 复制文件(保留权限)
shutil.copy2("source.txt", "destination.txt") # 复制文件(保留元数据)
# 复制目录
shutil.copytree("source_dir", "dest_dir") # 递归复制目录
# 移动文件/目录
shutil.move("old.txt", "new.txt") # 移动/重命名
shutil.move("old_dir", "new_dir")
# 删除目录(及其内容)
shutil.rmtree("temp_dir") # 递归删除
# 获取磁盘使用情况
usage = shutil.disk_usage(".")
print(f"总空间: {usage.total / (1024**3):.2f} GB")
print(f"已使用: {usage.used / (1024**3):.2f} GB")
print(f"可用: {usage.free / (1024**3):.2f} GB")
# 压缩和解压
shutil.make_archive("backup", "zip", "data") # 压缩目录
shutil.unpack_archive("backup.zip", "extract") # 解压文件
🗂️ os - 传统路径操作(了解即可)¶
Python
import os
# 路径拼接(传统方式)
path = os.path.join("data", "subdir", "file.txt")
# 路径信息
print(os.path.dirname(path)) # "data/subdir"
print(os.path.basename(path)) # "file.txt"
print(os.path.splitext(path)) # ("data/subdir/file", ".txt")
# 当前目录和父目录
print(os.getcwd()) # 当前工作目录
os.chdir("/path/to/dir") # 改变工作目录
# 列出目录内容
print(os.listdir(".")) # 列出当前目录
# 检查路径
print(os.path.exists(path)) # 是否存在
print(os.path.isfile(path)) # 是否是文件
print(os.path.isdir(path)) # 是否是目录
# 环境变量
print(os.environ["PATH"]) # 获取环境变量
os.environ["API_KEY"] = "xxx" # 设置环境变量
# ⚠️ 注意:新代码优先使用pathlib,更简洁、更安全
💡 实用场景¶
场景1: 批量重命名文件¶
Python
from pathlib import Path
def batch_rename(directory, pattern, replacement):
"""
批量重命名文件
例如: batch_rename("photos/", "IMG_", "Photo_")
将 IMG_001.jpg -> Photo_001.jpg
"""
path = Path(directory)
count = 0
for file in path.glob(f"*{pattern}*"):
new_name = file.name.replace(pattern, replacement)
new_path = file.parent / new_name
if not new_path.exists():
file.rename(new_path)
count += 1
print(f"重命名: {file.name} -> {new_name}")
print(f"共重命名 {count} 个文件")
# 使用
batch_rename("photos/", "IMG_", "Photo_")
场景2: 按扩展名整理文件¶
Python
from pathlib import Path
from collections import defaultdict
def organize_files(directory):
"""按文件扩展名整理文件到子目录"""
path = Path(directory)
files_by_ext = defaultdict(list)
# 分类文件
for file in path.iterdir():
if file.is_file():
ext = file.suffix[1:] if file.suffix else "no_extension"
files_by_ext[ext].append(file)
# 移动文件到对应的子目录
for ext, files in files_by_ext.items():
# 创建子目录
ext_dir = path / ext
ext_dir.mkdir(exist_ok=True)
# 移动文件
for file in files:
new_path = ext_dir / file.name
if not new_path.exists():
file.rename(new_path)
print(f"移动: {file.name} -> {ext}/{file.name}")
# 使用
organize_files("./downloads")
场景3: 查找并处理大文件¶
Python
from pathlib import Path
def find_large_files(directory, size_mb=10):
"""查找大于指定大小的文件"""
path = Path(directory)
size_bytes = size_mb * 1024 * 1024
large_files = []
for file in path.rglob("*"):
if file.is_file():
size = file.stat().st_size
if size > size_bytes:
large_files.append((file, size))
# 按大小排序
large_files.sort(key=lambda x: x[1], reverse=True) # lambda定义匿名函数,这里用作排序键
# 打印结果
for file, size in large_files:
print(f"{file}: {size / (1024**2):.2f} MB")
return large_files
# 使用
find_large_files(".", size_mb=5)
场景4: 备份重要文件¶
Python
from pathlib import Path
import shutil
from datetime import datetime
def backup_files(source_dir, backup_dir, pattern="*.py"):
"""备份匹配pattern的文件"""
source = Path(source_dir)
backup = Path(backup_dir)
# 创建带时间戳的备份目录
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
backup_path = backup / f"backup_{timestamp}"
backup_path.mkdir(parents=True, exist_ok=True)
# 复制文件
count = 0
for file in source.rglob(pattern):
# 保持目录结构
relative_path = file.relative_to(source)
dest_file = backup_path / relative_path
dest_file.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(file, dest_file)
count += 1
print(f"备份完成:{count} 个文件 -> {backup_path}")
# 使用
backup_files("./project", "./backups", "*.py")
场景5: 日志文件清理¶
Python
from pathlib import Path
from datetime import datetime, timedelta
def clean_old_logs(directory, days=7, pattern="*.log"):
"""删除超过指定天数的日志文件"""
path = Path(directory)
cutoff = datetime.now() - timedelta(days=days)
count = 0
for log_file in path.glob(pattern):
# 获取文件修改时间
mtime = datetime.fromtimestamp(log_file.stat().st_mtime)
if mtime < cutoff:
log_file.unlink()
count += 1
print(f"删除: {log_file.name} (修改于 {mtime.strftime('%Y-%m-%d')})")
print(f"清理完成:删除了 {count} 个旧日志")
# 使用
clean_old_logs("./logs", days=7)
📝 练习¶
练习1: 文件搜索¶
Python
from pathlib import Path
def search_files(directory, keyword, extension=None):
"""
在目录中搜索文件名包含keyword的文件
参数:
directory: 搜索目录
keyword: 文件名包含的关键词
extension: 可选,只搜索特定扩展名(如".py")
"""
# TODO: 实现这个函数
pass
# 测试
search_files(".", "test", ".py")
练习2: 空目录清理¶
Python
def remove_empty_directories(directory):
"""
递归删除目录下的所有空目录
提示:从最深的目录开始删除
"""
# TODO: 实现这个函数
pass
练习3: 文件同步工具¶
Python
def sync_directories(source, dest):
"""
将源目录同步到目标目录
- 只复制源目录中存在但目标目录中不存在的文件
- 跳过已存在且大小相同的文件
"""
# TODO: 实现这个函数
pass
🎯 自我检查¶
完成这个主题后,你应该:
- 优先使用pathlib而不是os
- 能熟练进行路径操作
- 能处理文件和目录的增删改查
- 能解决实际文件处理问题
- 不查资料完成上面的练习
📚 延伸阅读¶
下一步: 02 - 数据序列化