Python 如何安全删除目录树(即使里面有只读文件)

Python安全删除目录树需先修改只读权限再递归删除,推荐用shutil.rmtree配合onerror回调函数(如remove_readonly)处理PermissionError,该方法跨平台有效且避免shell命令风险。

Python 安全删除目录树(含只读文件)的关键是:先修改文件权限,再递归删除。直接调用 shutil.rmtree() 在遇到只读文件时会失败(特别是在 Windows 上),但只需配合一个简单的错误处理函数就能可靠解决。

使用 shutil.rmtree + onerror 参数

这是最常用且推荐的方式。通过 onerror 回调函数捕获权限错误(如 PermissionErrorOSError),临时赋予写权限后再重试删除。

示例代码:

import os
import stat
import shutil

def removereadonly(func, path, ): """强制移除只读文件或目录""" os.chmod(path, stat.S_IWRITE) # 设为可写 func(path) # 再次执行原操作(如 os.remove 或 os.rmdir)

安全删除整个目录树

shutil.rmtree("path/to/dir", onerror=remove_readonly)

兼容 Windows 和类 Unix 系统

上述方法在 Windows 和 Linux/macOS 均有效。Windows 下只读属性常导致删除失败;Linux/macOS 中若目录无写权限(chmod -w)也会触发类似问题。使用 stat.S_IWRITE 是跨平台安全的写权限标志,不会误开其他权限。

注意点:

  • 不要用 os.system("rm -rf")subprocess 调用 shell 命令——不跨平台、有注入风险、难调试
  • 避免手动遍历 + os.remove ——容易遗漏或顺序错误(必须从里往外删)
  • onerror 函数签名固定为 (func, path, exc_info),第三个参数是异常信息元组,通常用不到

更健壮的版本(带日志和异常细化)

生产环境建议加简单日志和错误分类,便于排查非权限类失败(如被进程占用):

import os
import stat
import shutil
import logging

logger = logging.getLogger(name)

def robust_remove_readonly(func, path, exc_info): if not os.path.exists(path): return try:

尝试解除只读

    os.chmod(path, stat.S_IWRITE | stat.S_IREAD | stat.S_IEXEC)
    func(path)
except Exception as e:
    logger.warning(f"仍无法删除 {path}: {e}")

shutil.rmtree("target_dir", onerror=robust_remove_readonly)

替代方案:pathlib(Python 3.4+)

如果你偏好 pathlib,它本身不提供递归删除,但可以封装 shutil.rmtree 并复用上面的 onerror

from pathlib import Path
import shuti

l

def safe_rmtree(p: Path): if p.is_dir(): shutil.rmtree(p, onerror=remove_readonly)

safe_rmtree(Path("my_folder"))

不复杂但容易忽略:只读问题本质是文件系统权限控制,不是 Python 的限制。只要提前“松绑”,标准库就能干净完成任务。