Skip to content

恭喜你进入 第二阶段:实战脚本篇

在这个阶段,我们将跨越“语法”和“应用”的鸿沟。作为开发者,你知道写代码最爽的时刻就是让电脑帮你做那些重复、枯燥的工作。

项目目标:编写一个 Python 脚本,一键清理你乱七八糟的“下载”文件夹(Downloads),根据文件后缀名自动归类到 Images, Docs, Installers 等文件夹中。

核心知识点

  1. pathlib:Python 3.4+ 引入的现代路径操作库(比老旧的 os.path 更优雅,面向对象风格)。

  2. shutil:用于高级文件操作(移动、复制、删除)。

  3. 字典映射:利用字典优化大量的 if-elif 判断。

  4. 异常处理:防止因为一个文件移动失败(如被占用)导致整个脚本崩溃。


前置准备:理解路径操作

在 Node.js 中你可能习惯用 path.join(__dirname, 'file.txt')

在现代 Python 中,我们使用 pathlib.Path 对象,它重载了 / 运算符,让路径拼接非常直观。

Python

Python
from pathlib import Path

# 获取当前脚本所在目录
current_dir = Path.cwd() 

# 路径拼接 (是不是比 os.path.join 优雅?)
target_file = current_dir / "downloads" / "test.jpg"

print(target_file.name)   # test.jpg
print(target_file.suffix) # .jpg
print(target_file.stem)   # test
print(target_file.exists()) # True/False

实战代码:文件整理神器 (File Organizer)

建议在桌面上新建一个测试文件夹(比如 test_folder),里面随便放几个 txt, jpg, pdf 文件来运行此脚本,不要直接在你的重要目录运行,防止误操作

新建文件 organizer.py

Python

Python
import shutil
from pathlib import Path

# 1. 配置:定义文件后缀与目标文件夹的映射关系
# 这种配置方式比写一堆 if suffix == '.jpg' 更易维护
FILE_FORMATS = {
    "Images":    [".jpg", ".jpeg", ".png", ".gif", ".svg", ".webp"],
    "Documents": [".pdf", ".docx", ".doc", ".txt", ".xlsx", ".pptx", ".md"],
    "Archives":  [".zip", ".rar", ".7z", ".tar", ".gz"],
    "Code":      [".py", ".js", ".html", ".css", ".java", ".json"],
    "Installers":[".exe", ".msi", ".dmg", ".pkg", ".deb"]
}

def organize_directory(path_str):
    """
    核心整理函数
    :param path_str: 要整理的文件夹路径 (字符串)
    """
    # 将字符串转换为 Path 对象
    base_dir = Path(path_str)

    # 检查路径是否存在
    if not base_dir.exists():
        print(f"❌ 错误:路径不存在 -> {base_dir}")
        return

    print(f"📂 正在整理:{base_dir} ...")

    # 2. 遍历目录下的所有内容 (iterdir 类似 ls 命令)
    for item in base_dir.iterdir():
        # 我们只处理文件,忽略文件夹,避免递归混乱
        if item.is_dir():
            continue
        
        # 忽略脚本自身 (防止把自己也移走了)
        if item.name == Path(__file__).name:
            continue

        # 获取文件后缀 (转小写,防止 .JPG 和 .jpg 识别为不同)
        file_suffix = item.suffix.lower()
        
        # 3. 核心逻辑:查找该文件属于哪个分类
        destination_folder = "Others" # 默认分类
        
        # 遍历配置字典
        # folder_name 是键 (如 "Images"), extensions 是值 (列表)
        for folder_name, extensions in FILE_FORMATS.items():
            if file_suffix in extensions:
                destination_folder = folder_name
                break # 找到了就停止循环
        
        # 4. 移动操作
        target_dir = base_dir / destination_folder
        
        # 这一步很关键:如果目标文件夹不存在,自动创建
        # exist_ok=True 表示如果文件夹已存在,不报错
        target_dir.mkdir(exist_ok=True)
        
        # 构建目标文件的完整路径
        target_path = target_dir / item.name
        
        try:
            # 移动文件 (shutil.move)
            shutil.move(str(item), str(target_path))
            print(f"✅ 移动: {item.name} -> {destination_folder}/")
        except Exception as e:
            # 5. 异常处理:如果是“文件已存在”或“被占用”,打印错误但不崩溃
            print(f"⚠️ 跳过: {item.name} (原因: {e})")

if __name__ == "__main__":
    # 输入你要整理的路径,"." 代表当前目录
    target_path = input("请输入要整理的文件夹路径 (默认为当前目录): ").strip() or "."
    organize_directory(target_path)
    print("\n🎉 整理完成!")

深度解析 (Document)

1. 为什么用 pathlib 而不是 os

  • 传统方式 (os): os.path.join(dir, file) 返回的是字符串。你需要手动切分字符串来获取后缀名。

  • 现代方式 (pathlib): Path(dir) / file 返回的是对象。你可以直接调用 .suffix (后缀), .stem (文件名), .parent (父目录)。这更符合 OOP (面向对象) 思维,代码可读性极高。

2. 字典结构的设计逻辑

作为开发者,我们要避免“硬编码 (Hard Coding)”。

  • 初级写法:

    Python

    Python
    if suffix == '.jpg' or suffix == '.png':
        folder = 'Images'
    elif suffix == '.pdf':
        folder = 'Docs'

    这种写法如果要增加格式,你需要改动逻辑代码。

  • 高级写法 (配置分离):

    使用字典 FILE_FORMATS。如果未来你想支持 .mp4,只需要在字典里的 Videos 列表加一项即可,逻辑代码(Loop部分)完全不需要动。

3. try...except 的重要性

在文件操作中,不可控因素非常多:

  • 文件正在被 Word 打开(无法移动)。

  • 目标文件夹里已经有一个同名文件(Windows 下会报错,Linux 下可能会覆盖)。

  • 权限不足。

    如果不加 try...except,处理第 3 个文件报错时程序就会挂掉,剩下的 97 个文件就不会被处理。


课后挑战 (Homework)

为了让你“由浅入深”,请尝试在上述代码基础上增加以下功能(遇到困难可以把需求发给我,我给你提示):

  1. 处理重名文件:目前的 shutil.move 如果遇到同名文件可能会报错。请修改逻辑:如果目标文件夹已有 file.txt,则自动重命名为 file_1.txt 再移动。

  2. 按日期归类:不再按后缀名,而是按文件的“修改日期”归类。例如创建 2023-10, 2023-11 文件夹。提示:使用 item.stat().st_mtime 获取时间戳。

搞定这个脚本,你就掌握了 Python 处理系统任务的核心能力。下一步我们将进入 Web 交互与爬虫 领域,去获取互联网上的数据。准备好了吗?

坚持是一种品格