优先用os.walk递归遍历,配合try/except捕获单个目录错误;删除前必开dry_run开关并白名单过滤site-packages等敏感路径;先判文件类型再调用对应删除函数;排除脚本自身路径,避免自删。

用 os.walk 递归找文件比 glob 更稳
递归遍历目录时,os.walk 能天然处理深层嵌套、符号链接(默认跳过)、权限受限子目录的跳过逻辑;而 glob.glob("**/*.pyc", recursive=True) 在遇到无读取权限的目录会直接抛 PermissionError 中断整个流程。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 优先用
os.walk,配合try/except OSError捕获单个目录访问失败,不中断整体扫描 - 避免用
pathlib.Path.rglob处理超大目录树——它会一次性构建所有匹配路径对象,内存占用明显更高 - 后缀匹配别写
file.endswith(".cache"),改用pathlib.Path(file).suffix.lower() in {".pyc", ".pyo", ".cache"},兼容大小写和点号前有内容的情况(如.npy.cache)
删之前必须加 dry_run 开关和路径白名单
误删 __pycache__ 本身没事,但删掉项目根目录下 venv/lib/python3.11/site-packages/django/core/cache.py 这种就真崩了。真实场景里,缓存文件常和源码混在同一个目录(比如 pytest 的 .pytest_cache 是目录,*.log 可能是运行日志而非缓存)。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 默认开启
dry_run=True,只打印将删路径,确认无误再关掉 - 硬编码白名单:跳过
"site-packages"、"dist"、"build"等敏感路径名(不是后缀!),用if "site-packages" in str(path.parent): continue - 别依赖文件修改时间过滤——有些构建缓存刚生成就该删,有些日志文件三天没动但不能删
shutil.rmtree 删目录比 os.remove 删文件更常用但更危险
像 .mypy_cache、.pytest_cache、__pycache__ 都是目录,用 os.remove 会报 IsADirectoryError;反过来,对普通文件用 shutil.rmtree 会报 NotADirectoryError。两者不能混用。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 先用
path.is_file()和path.is_dir()明确类型,再分发删除逻辑 - 删目录时加
onerror回调:例如遇到权限问题,尝试os.chmod(path, 0o755)后重试,而不是直接跳过 - Windows 下注意
shutil.rmtree对只读文件夹可能失败,需额外处理stat.S_IWRITE标志位
清理脚本要防自己被删——别把脚本放进扫描路径
常见翻车现场:把清理脚本命名为 cleanup.py 放在项目根目录,又设置后缀过滤为 ["py", "pyc"],结果脚本刚跑一半就被自己删了,进程卡死或报 IOError: [Errno 9] Bad file descriptor。
实操建议:
立即学习“Python免费学习笔记(深入)”;
- 脚本自身路径必须从扫描范围排除:
if str(path.resolve()) == str(Path(__file__).resolve()): continue - 别用
os.getcwd()当起点,用绝对路径启动扫描(如Path.home() / "Library/Caches"),避免相对路径引发意外覆盖 - 生产环境建议加锁文件(
cleanup.lock),防止同一路径被多个实例并发清理导致状态错乱
真正麻烦的从来不是“怎么删”,而是“删哪些才安全”——路径判断逻辑一旦漏掉一个例外,恢复成本远高于多删几个缓存文件。


















