PermissionError 权限被拒:Errno 13 Permission denied 速查
更新时间:2026-10-24。FAQ 速查页,面向写文件、改文件、删文件时撞
PermissionError的同学。这个报错字面上是「操作系统不让你碰这个文件」,但「不让碰」的真因分六根轴:文件正被别的进程占用(Windows 上最典型)、文件本身是只读属性、目标目录没有写权限、习惯性套 sudo 反而把事情搞砸、编辑器/杀软/同步盘在背后持锁、以及挂载盘把权限位丢了。报错原文里那个路径就是线索起点,顺着权限位和占用者两头查基本必中。路径根本不存在(不是没权限)归 FileNotFoundError 文件不存在速查 管。
本文要回答的问题
PermissionError: [Errno 13]和[WinError 5]、[WinError 32]差在哪?- 文件明明是我的,为什么写不进去?
- 为什么
sudo python3跑通了,正常跑反而被拒? - Windows 上「另一个程序正在使用此文件」怎么找出是谁占的?
- 权限修好后,为什么过两天又复发?
一、报错原文与典型现象
报错就长在 traceback 最后一行,但 Windows 和 Linux 的变体要分清(工程路径以 /proj/demo 占位):
$ python3 /proj/demo/save.py
Traceback (most recent call last):
File "/proj/demo/save.py", line 3, in <module>
open("/proj/demo/out/result.csv", "w").write("ok")
PermissionError: [Errno 13] Permission denied: '/proj/demo/out/result.csv'C:\proj\demo> python save.py
PermissionError: [WinError 32] 另一个程序正在使用此文件,进程无法访问。: 'C:\\proj\\demo\\out\\result.csv'$ sudo python3 /proj/demo/save.py
# 跑通了,但 out/ 下生成的文件属主变成 root
# 之后普通用户再跑一律 PermissionError——sudo 埋的雷读报错先抓两件事:错误号是 13(POSIX 通用权限拒绝)还是 WinError 32(典型的文件被占用);被拒的路径是文件本身还是它所在的目录——写文件要的是「目录的写权限 + 文件(若已存在)的写权限」,两者缺一都报 13。
二、病因处置速查表
| 报错现象 / 场景 | 可能原因 | 快速验证 | 处置 |
|---|---|---|---|
| WinError 32 文件被占用 | Excel/编辑器/上次没关的句柄持锁 | 资源监视器搜文件名;Linux 用 lsof 路径 | 关掉占用程序;代码里 with open 确保关闭 |
| Errno 13 且文件已存在 | 文件只读(chmod a-w 或 Windows 只读属性) | ls -l 路径 看 w 位;Windows 右键属性 | chmod u+w 路径;取消只读属性 |
| Errno 13 且文件不存在 | 所在目录无写权限 | ls -ld 目录 看 w 位 | chmod u+w 目录 或换可写输出目录 |
| 只有 sudo 才能写 | 目录属 root 或其它用户 | ls -ld 目录 看属主 | sudo chown -R 用户 目录 把属主改回来 |
| sudo 跑过之后正常跑全拒 | sudo 生成的文件属主是 root | ls -l 看新文件属主 | sudo chown 改回;以后别用 sudo 跑脚本 |
| 写到 U盘/共享盘必拒 | FAT32 无权限位 / samba 挂载丢权限 | mount 看文件系统类型 | 换本地 ext4/NTFS 路径,或调整挂载选项 |
| 杀软扫描瞬间偶发被拒 | 实时防护短暂持锁 | 关闭实时防护复测 | 输出目录加白名单;写失败重试一次 |
| 程序自己生成的文件自己改不动 | 上次运行没 close,同进程句柄泄漏 | 代码里是否裸 open 无 with | 一律 with open(...) as f: 写法 |
三、排查决策图
下面这张图是权限类报错的标准排查路线,颜色按角色区分:红是报错入口与命中的根因,蓝是排查动作,绿是通过分支,橙是修复动作,紫是防复发沉淀。
读这张图抓住一个分水岭:先查「有没有别人拿着这个文件」,再查「权限位给不给你写」。Windows 上前者占大头(Excel 开着 CSV 是国民级事故),Linux 服务器上后者占大头(部署目录属 root、脚本跑在普通用户)。两边都查过还拒,才轮到挂载盘丢权限这条偏门。
四、逐条排查展开
Windows 文件锁:先找占用者,别先改权限。 WinError 32 的意思非常具体——另一个进程打开了这个文件且没设共享写。最常见占用者:Excel 开着你要写的 CSV、编辑器没关、上一次程序崩溃留下僵尸句柄。确认手段:资源监视器(resmon)的 CPU 标签页搜文件名,或 PowerShell 跑 Get-Process 逐个排。Linux 等价物是 lsof /proj/demo/out/result.csv,一列 PID 直接点名。修完占用后,代码侧根治是一律 with open(...) as f:,块结束句柄必关,不再给泄漏留门。
只读属性是两层:文件只读和目录无写。 改已存在的文件要文件本身的 w 位;新建/删除文件要的是目录的 w 位——很多人 chmod +w file 后发现还是拒,因为真正缺权限的是目录。一次性看全:
ls -l /proj/demo/out/result.csv # 文件本身的权限位
ls -ld /proj/demo/out # 目录的权限位与属主文件缺 w 就 chmod u+w,目录缺 w 就 chmod u+w /proj/demo/out。Windows 对应右键属性里的「只读」勾选项,目录同理。
sudo 是埋雷,不是修复。 「PermissionError 就套 sudo」是最常见的错误反射。sudo 跑通只是因为 root 无视权限位,代价是:这次运行生成的所有文件属主都变成 root,下次普通用户跑——连删自己上次生成的文件都会被拒,坑越滚越大。正确方向反过来:脚本永远用普通用户跑,权限不够就改目录属主:
sudo chown -R $USER:$USER /proj/demo/out已用 sudo 跑过的,同样用这条把属主赎回来。
写系统目录不如换目录。 /usr/local、/var/log、C:\Program Files 这类位置本来就设计为普通用户不可写,和应用商店沙盒目录同理。与其 chmod 系统目录(引入安全风险),不如把输出改到用户自己的地盘:~/.local/share/<应用名>、项目内 /proj/demo/out/、或环境变量 XDG_DATA_HOME 指向的位置。Windows 下对应 %APPDATA% 与 %LOCALAPPDATA%。
挂载盘与同步盘丢权限。 FAT32/exFAT U 盘没有 POSIX 权限位,chmod 无效;samba/NFS 挂载选项不对时,远端文件的属主映射到本地会变成 nobody;网盘同步目录(Desktop/Documents 被同步接管的 Windows 机器)会在同步瞬间持锁。表现是「本地盘能写、那个盘必拒」。处置:输出路径换回本地常规文件系统;samba 挂载加 uid=、file_mode= 选项;同步盘目录里的高频写文件挪出去。
偶发被拒考虑杀软与索引。 Windows Defender 实时防护、桌面搜索索引会在文件刚写完的瞬间短暂持锁,程序紧接着 reopen 就撞 WinError 32/5。特征:失败是偶发的、重跑一次就过。处置分两层:输出目录加杀软白名单;代码里写失败后 sleep 0.5s 重试一次(最多三次),这是工业界处理 AV 竞态的通行做法。
SSH 到服务器跑时的专属坑。 部署机上脚本跑在 www-data、nginx 这类服务账户下,而你用个人账户上传的文件属主是你自己——服务账户自然被拒。确认:ps aux | grep python 看进程属主,对比 ls -l 的文件属主。处置:chown 到服务账户,或建一个共同的部署组用组权限(chgrp + chmod g+w)解决。
五、规范做法与预防
- 铁律:不用 sudo 跑业务脚本,权限不够就 chown/chmod 修目标,不抬进程权限。
- 一律
with open(...):句柄必关,从根上消灭「自己锁自己」。 - 输出目录跟随项目:
/proj/demo/out/入库时带.gitkeep,属主即开发者,不碰系统目录。 - 写失败重试一次:捕获 PermissionError 后短 sleep 重试 ≤3 次,兼容杀软/同步盘竞态。
- 部署文档写明属主:README 里写「本服务以 xxx 用户运行,数据目录需 chown xxx」。
- CI 里跑一遍非特权用户测试:权限类问题在 root 跑的开发机上永远不会暴露。
这一篇在知识体系里的位置
本篇是 Python 排错速查簇的权限篇,定位「文件在、但没权限碰」:路径本身不存在看 FileNotFoundError 文件不存在速查;装包时的权限拒绝(site-packages 无写权限、--user 方案)看 pip install 安装失败速查;模块找不到看 ModuleNotFoundError 模块找不到速查;解释器版本不兼容看 Python 版本不兼容报错速查;文件操作与异常处理的概念底座看 Python 入门导览。ls -l + ls -ld + lsof 三件确认套在一切权限类报错里通用。
一句话总结
PermissionError 先分两步:查占用(Windows 资源监视器搜文件名 / Linux lsof 路径,WinError 32 基本就是占用)再查权限位(ls -l 看文件 w 位、ls -ld 看目录 w 位与属主)。只读就 chmod u+w,目录无写就修目录,属主不对就 chown 改回——唯独不要套 sudo 跑脚本,那只是把属主推给 root 埋下一轮的雷。挂载盘丢权限换本地路径,杀软竞态加白名单加有限重试,代码一律 with open 确保句柄关闭,这个报错基本绝迹。