os.remove()在Windows下报PermissionError主因是文件被其他进程占用句柄,需用psutil以管理员权限遍历进程句柄定位并安全终止对应进程,或检查Python自身未关闭的open()文件。

为什么os.remove()报错“PermissionError: The process cannot access the file because it is being used by another process”
Windows 下删不掉文件,绝大多数情况是某个进程正持有该文件的句柄(比如日志被notepad.exe打开、Excel 正在读取 CSV、Python 自己的 open() 没关、甚至杀毒软件在扫描)。此时 os.remove() 直接抛出 PermissionError,不是权限问题,而是句柄被占——得先定位并释放它。
用psutil查哪个进程在占用目标文件
psutil 是唯一能跨进程遍历句柄的可靠方案。注意:必须以管理员权限运行脚本,否则无法访问其他用户或系统进程的句柄。
关键逻辑是遍历所有进程的打开文件列表,匹配绝对路径:
import psutil
import os
<p>def find_process_holding_file(filepath):
filepath = os.path.abspath(filepath)
for proc in psutil.process_iter(['pid', 'name']):
try:</p><h1>Windows 下用 open_files();Linux/macOS 用 open_files() 或 files()</h1><pre class='brush:python;toolbar:false;'> for file in proc.open_files():
if os.path.samefile(file.path, filepath):
return proc
except (psutil.AccessDenied, psutil.NoSuchProcess):
continue
return None示例
p = find_process_holding_file(r"C:\temp\locked.txt") if p: print(f"PID {p.pid}, name: {p.name()}")
注意点:
立即学习“Python免费学习笔记(深入)”;
-
os.path.samefile()比字符串相等更安全,能处理符号链接、大小写、短路径名(8.3格式)等问题 -
proc.open_files()在 Windows 上返回的是(path, fd)元组,fd通常是 -1;Linux/macOS 返回对象含更多字段 - 某些进程(如
svchost.exe)即使有管理员权限也可能拒绝访问句柄,这时会抛psutil.AccessDenied,需跳过
强制关闭句柄前必须确认风险
直接调用 proc.terminate() 或 proc.kill() 可能导致数据丢失或程序崩溃。更稳妥的做法是只关闭特定句柄(需 Windows API 支持),但 psutil 不提供该能力——它只能杀进程,不能杀单个句柄。
所以实际操作分两步:
- 若进程是你自己启动的(如另一个 Python 脚本、测试中的 Excel 实例),优先用
proc.terminate()等待其正常退出 - 若进程是第三方且无响应(如卡死的 Notepad),再用
proc.kill() - 绝对不要对
explorer.exe、lsass.exe、services.exe等系统进程调用kill(),会导致蓝屏或登录失败
示例安全删除流程:
import time
<p>def safe_remove_file(filepath):
p = find_process_holding_file(filepath)
if not p:
os.remove(filepath)
return True</p><pre class='brush:python;toolbar:false;'>print(f"Killing process {p.name()} (PID {p.pid})...")
try:
p.terminate()
try:
p.wait(timeout=3)
except psutil.TimeoutExpired:
p.kill() # 强制
time.sleep(0.5) # 给系统一点释放时间
os.remove(filepath)
return True
except (psutil.NoSuchProcess, PermissionError):
return Falsesafe_remove_file(r"C:\temp\locked.txt")
替代方案:不用psutil时的临时绕过方法
如果无法装 psutil(如受限环境),可尝试以下低侵入方式,但成功率有限:
- 用
subprocess调用handle.exe(Sysinternals 工具),需提前下载并配置 PATH - 改用
shutil.move()把文件移到回收站或临时目录(send2trash库),避开删除阶段的句柄检查 - 加重试循环 + 延迟:
for _ in range(5): try: os.remove(...) break except PermissionError: time.sleep(0.2),适合瞬时占用(如刚写完日志还没 flush)
这些只是缓解,不是根治。真正要确定性释放句柄,还是得靠 psutil 定位 + 明确干预。
最易被忽略的一点:Python 自身的 open() 忘记 .close() 或没用 with 语句,是本地开发中最常见的“自己锁自己”场景——检查你的代码里有没有裸 open()。


















