【Python】基础语法入门(二十四)——文件与目录操作进阶:安全、高效地处理本地数据


📁 说明 :文件和目录操作是绝大多数 Python 应用的基础功能------无论是读取配置、保存日志,还是批量处理数据。本篇深入讲解 pathlibosshutilglob 等模块的高级用法 ,并强调安全性、健壮性与跨平台兼容性,助你写出专业级的文件处理代码。

你将掌握:

  • pathlib 实现现代、面向对象的路径操作
  • 安全创建/删除目录(避免 FileExistsError 和空目录残留)
  • 高效遍历大型目录(使用生成器避免内存爆炸)
  • 批量重命名、移动、复制文件
  • 处理权限、元数据与临时文件
  • 防范路径遍历等安全风险

1. 为什么推荐 pathlib?(vs os.path

特性 os.path pathlib.Path
风格 函数式(os.path.join("a", "b") 面向对象(Path("a") / "b"
可读性 较低 高(支持运算符)
跨平台 需注意分隔符 自动处理
方法丰富度 基础 内置 .read_text(), .mkdir()

从 Python 3.4 起,官方推荐使用 pathlib


2. 核心操作实战

2.1 创建目录(安全且递归)

python 复制代码
from pathlib import Path

# 创建单层目录(存在则报错)
Path("logs").mkdir(exist_ok=True)

# 创建多层目录(如 a/b/c)
Path("data/raw/images").mkdir(parents=True, exist_ok=True)

🔑 参数说明:

  • parents=True:自动创建父目录
  • exist_ok=True:目录已存在时不报错

2.2 安全写入文件(避免覆盖/损坏)

方法1:原子写入(推荐)
python 复制代码
from pathlib import Path
import tempfile

def safe_write(file_path: Path, content: str):
    """先写临时文件,再原子替换原文件"""
    with tempfile.NamedTemporaryFile(
        dir=file_path.parent,
        delete=False,
        mode="w",
        encoding="utf-8"
    ) as tmp:
        tmp.write(content)
        tmp_path = Path(tmp.name)
    
    # 原子替换(POSIX 系统保证)
    tmp_path.replace(file_path)

✅ 优势:

  • 写入失败不破坏原文件
  • 避免程序崩溃导致半写入文件
方法2:简单覆盖(适合非关键数据)
python 复制代码
Path("config.json").write_text('{"debug": true}', encoding="utf-8")

2.3 遍历目录(高效 & 可控)

场景1:仅当前目录下的文件
python 复制代码
for item in Path("docs").iterdir():
    if item.is_file():
        print(item.name)
场景2:递归遍历所有 .txt 文件
python 复制代码
# 使用 glob(简洁)
for txt_file in Path("project").rglob("*.txt"):
    print(txt_file)

# 使用 walk(更灵活)
for root, dirs, files in Path("data").walk():  # Python 3.12+
    for f in files:
        if f.endswith(".log"):
            print(root / f)

⚠️ 注意

  • rglob() 返回生成器,内存友好
  • 旧版本 Python(❤️.12)用 os.walk() + Path

2.4 批量操作:重命名、移动、删除

示例:为图片添加前缀
python 复制代码
from pathlib import Path

img_dir = Path("photos")
for i, img in enumerate(img_dir.glob("*.jpg"), start=1):
    new_name = f"vacation_{i:03d}.jpg"
    img.rename(img_dir / new_name)
移动文件到归档目录
python 复制代码
archive = Path("archive")
archive.mkdir(exist_ok=True)

for log in Path("logs").glob("*.log"):
    log.replace(archive / log.name)  # 移动(同盘)或复制+删除(跨盘)
安全删除目录(非空)
python 复制代码
import shutil

# 删除整个目录树
shutil.rmtree("temp_data", ignore_errors=True)

# 或用 pathlib(Python 3.12+)
Path("temp_data").rmtree(ignore_errors=True)

不要用 os.rmdir():只能删空目录


3. 获取文件元数据

python 复制代码
from pathlib import Path
import datetime

p = Path("report.pdf")

if p.exists():
    stat = p.stat()
    print(f"大小: {stat.st_size} 字节")
    mtime = datetime.datetime.fromtimestamp(stat.st_mtime)
    print(f"修改时间: {mtime}")
    
    # 检查权限(Unix-like 系统)
    print(f"可读: {os.access(p, os.R_OK)}")

💡 提示:

  • st_mtime = 修改时间
  • st_ctime = 创建时间(Windows)/ 状态变更时间(Unix)

4. 安全性:防范路径遍历攻击

当处理用户输入的文件名时,必须校验路径合法性

危险示例(切勿模仿!)

python 复制代码
# 用户输入 filename = "../../../etc/passwd"
filename = input("输入文件名: ")
Path("uploads") / filename  # 可能逃出 uploads 目录!

安全做法:限制在指定目录内

python 复制代码
def safe_join(base_dir: Path, user_path: str) -> Path:
    """确保 user_path 不会逃出 base_dir"""
    resolved = (base_dir / user_path).resolve()
    if not resolved.is_relative_to(base_dir.resolve()):
        raise ValueError("非法路径!")
    return resolved

# 使用
try:
    safe_path = safe_join(Path("uploads"), "../../secret.txt")
except ValueError as e:
    print(e)  # 非法路径!

🔒 关键函数

  • Path.resolve():解析绝对路径(含 ..
  • Path.is_relative_to():检查是否在指定目录下(Python 3.9+)

5. 临时文件与目录(回顾 + 进阶)

自动清理的临时工作区

python 复制代码
import tempfile
from pathlib import Path

with tempfile.TemporaryDirectory() as tmp_dir:
    work_path = Path(tmp_dir)
    
    # 在此目录下进行复杂操作
    (work_path / "input.csv").write_text("...")
    process_data(work_path)
    
    # 退出 with 块后自动删除整个目录

✅ 适用场景:

  • 解压 ZIP 后处理文件
  • 生成中间报告
  • 测试隔离环境

6. 常见陷阱与解决方案

问题 原因 解决方案
FileNotFoundError 父目录不存在 mkdir(parents=True)
中文文件名乱码 编码未指定 open(..., encoding="utf-8")
权限拒绝 无写权限 检查 os.access() 或捕获 PermissionError
跨平台路径错误 硬编码 \/ 始终用 Pathos.path.join
删除非空目录失败 用了 os.rmdir shutil.rmtree

7. 实战:构建一个"日志归档工具"

整合所学知识,编写一个实用小工具:

python 复制代码
#!/usr/bin/env python3
from pathlib import Path
import shutil
from datetime import datetime

def archive_logs(log_dir: Path, archive_dir: Path):
    """将 7 天前的日志移至归档目录"""
    archive_dir.mkdir(parents=True, exist_ok=True)
    
    now = datetime.now()
    for log_file in log_dir.glob("app_*.log"):
        stat = log_file.stat()
        mtime = datetime.fromtimestamp(stat.st_mtime)
        days_old = (now - mtime).days
        
        if days_old >= 7:
            # 构建带日期的归档名
            date_str = mtime.strftime("%Y%m%d")
            stem = log_file.stem
            ext = log_file.suffix
            new_name = f"{stem}_{date_str}{ext}"
            
            target = archive_dir / new_name
            log_file.replace(target)
            print(f"归档: {log_file.name} → {new_name}")

if __name__ == "__main__":
    archive_logs(Path("logs"), Path("logs/archive"))

✨ 功能亮点:

  • 自动创建归档目录
  • 按修改时间判断是否过期
  • 重命名包含日期,避免冲突

8. 总结:文件操作黄金法则

  1. pathlib.Path 代替字符串拼接路径
  2. 写入关键文件时使用原子操作
  3. 遍历大目录用生成器(glob, iterdir
  4. 处理用户输入路径时严格校验
  5. 删除目录用 shutil.rmtree
  6. 始终指定文本编码(utf-8

🐍 记住

"文件系统是不可靠的外部世界,你的代码必须做好防御。"

------ 专业开发者的基本素养


下一步练习

  1. 为你的 To-Do List 添加"自动备份"功能 (每天备份 tasks.jsonbackup/
  2. 编写一个"清理下载文件夹"脚本(按扩展名分类移动文件)
  3. 实现一个安全的文件上传接口(校验路径、限制大小、扫描内容)

🧹 掌控文件系统,就是掌控数据的命脉。

用稳健的代码,守护你的每一份数据!

继续精进,成为文件操作的 Python 高手!

相关推荐
Das12 小时前
【计算机视觉】05_不变性
人工智能·计算机视觉
是有头发的程序猿2 小时前
Python爬虫实战:面向对象编程构建高可维护的1688商品数据采集系统
开发语言·爬虫·python
lkbhua莱克瓦242 小时前
多线程综合练习3
java·开发语言·多线程·githup
摸鱼仙人~2 小时前
企业级 RAG 问答系统开发上线流程分析
后端·python·rag·检索
跨境卫士情报站2 小时前
摆脱砍单魔咒!Temu 自养号系统化采购,低成本高安全
大数据·人工智能·安全·跨境电商·亚马逊·防关联
OAK中国_官方2 小时前
将Roboflow工作流引入OAK4:简化实时计算机视觉
人工智能·计算机视觉
andwhataboutit?2 小时前
smolagent框架
学习
吴爃2 小时前
N8N调用系统接口进行AI分析
运维·人工智能·ai
老鱼说AI2 小时前
经典论文精读第一期:DeepSeek-R1-Zero ——RL奇迹
人工智能·分布式·深度学习·神经网络·自然语言处理·nlp·transformer