os.rmdir() 直接遍历会失败,因为它只能删除空目录;从上往下遍历时父目录非空,触发OSError;必须用os.walk(path, topdown=False)自底向上遍历,确保先删子目录再删父目录。

为什么 os.rmdir() 直接遍历会失败
因为 os.rmdir() 只能删空目录,而从上往下遍历时,父目录往往非空(里面还有子目录),导致报错 OSError: [WinError 145] 目录不是空的 或 Directory not empty。必须自底向上删——先处理最深层的空文件夹,再逐层回退。
用 os.walk() 配合 topdown=False 真正生效的关键
os.walk() 默认是自顶向下(topdown=True),但设为 topdown=False 后,它会先 yield 所有子目录,最后才 yield 父目录,天然满足“先子后父”的删除顺序。注意:这不是简单倒序,而是 walk 内部按深度优先逆序生成路径。
- 必须用
for root, dirs, files in os.walk(path, topdown=False),不能对结果 list 做reversed() -
dirs和files是当前root下的直接子项,判断空目录只需检查not dirs and not files - 删之前建议加
os.path.isdir(root)防止符号链接或权限异常干扰
实际清理时要避开当前工作目录和系统关键路径
脚本若在待清理目录内运行,os.rmdir() 会因“当前目录被占用”抛出 OSError: [WinError 32] 另一个程序正在使用此文件;Linux 下也可能遇到类似问题。更危险的是误传根路径如 / 或 C:\。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
- 开头强制校验:
if not os.path.abspath(path).startswith(os.path.abspath('.')):拒绝清理当前目录之外的路径(可按需放宽) - 跳过挂载点(Linux/macOS):
if os.stat(root).st_dev != os.stat(os.path.dirname(root)).st_dev:避免跨文件系统误删 - 加 dry-run 开关:
if not dry_run: os.rmdir(root),默认只打印将删哪些路径
Windows 下中文路径 PermissionError 的临时解法
某些 Windows 版本对带中文、空格或特殊符号的路径调用 os.rmdir() 会抛 PermissionError: [WinError 5] 拒绝访问,并非权限不足,而是 Python 3.7+ 的底层 API 行为变化所致。
- 改用
shutil.rmtree(root)虽然能删,但风险高——万一判断逻辑有误,会连带删掉非空目录内容 - 稳妥做法:捕获该异常后,用
subprocess.run(['rmdir', '/q', root], shell=True)(仅 Windows) - 更推荐统一用
pathlib.Path(root).rmdir(),它在多数情况下比os.rmdir()对 Unicode 路径更鲁棒
实际跑起来前,务必先用 dry_run=True 看一遍输出,尤其注意路径是否含意料之外的隐藏文件(比如 .DS_Store 或 Thumbs.db)——它们会让目录“看似非空”。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










