windows上最常见的是permissionerror: [errno 13] permission denied,偶尔遇到access is denied或the process cannot access the file because it is being used by another process。

Python直接读取被锁定文件会报什么错
Windows上最常见的是PermissionError: [Errno 13] Permission denied,偶尔遇到Access is denied或The process cannot access the file because it is being used by another process。Linux/macOS一般不会因“占用”报错(除非是写锁且你尝试写),但若文件正被其他进程以O_EXCL或强制独占方式打开,open()仍可能失败——不过这类情况极少,真正卡住你的几乎全是Windows场景。
用win32file.CreateFile绕过共享锁
标准open()默认请求FILE_SHARE_READ | FILE_SHARE_WRITE,一旦对方没设共享标志,就进不去。而win32file.CreateFile允许你显式控制访问模式和共享标志,把“我要只读、不抢写权、也不在乎别人是否在写”这个意图传给系统。
需要先装pywin32:pip install pywin32
关键参数说明:
-
dwDesiredAccess=win32file.GENERIC_READ:只要读权限 -
dwShareMode=win32file.FILE_SHARE_READ | win32file.FILE_SHARE_WRITE:告诉系统“我允许别人同时读或写这个文件”,哪怕对方没设共享,这里强行声明兼容性 -
dwCreationDisposition=win32file.OPEN_EXISTING:不创建,只打开已有文件 -
dwFlagsAndAttributes=win32file.FILE_ATTRIBUTE_NORMAL:普通属性,不加FILE_FLAG_NO_BUFFERING之类特殊标记
示例代码片段:
import win32file
import win32event
import msvcrt
<p>def read_locked_file(path):
try:
handle = win32file.CreateFile(
path,
win32file.GENERIC_READ,
win32file.FILE_SHARE_READ | win32file.FILE_SHARE_WRITE,
None,
win32file.OPEN_EXISTING,
0,
None
)</p><h1>转为Python文件对象</h1><pre class="brush:python;toolbar:false;"> fd = msvcrt.open_osfhandle(handle, os.O_RDONLY)
with os.fdopen(fd, 'rb') as f:
return f.read()
except Exception as e:
print(f"读取失败: {e}")
return None
为什么不能总用try/except捕获PermissionError后重试
重试逻辑治标不治本。如果文件被记事本、Excel、Log4j日志轮转器等长期持有句柄,PermissionError会持续出现,盲目轮询只是浪费CPU、延迟响应,还可能掩盖真实问题——比如对方根本没释放句柄,或者你本不该读正在写的日志。
更务实的做法是:
- 确认读取必要性:是否真要读“正在写入中”的文件?日志类场景优先查归档文件或用
tail -f式监听 - 检查对方进程是否可配置:如Logback可设
<append>true</append>并启用prudent="true"来支持多进程写入 - 用
handle.exe(Sysinternals工具)查谁锁着文件:handle.exe -a "yourfile.log",比猜强得多
Linux/macOS下其实没那么麻烦,但要注意mmap和O_APPEND
Unix系文件锁本质是 advisory(建议性),open()通常能成功,但读到的内容可能不一致——尤其对方正用O_APPEND追加写时,你seek(0)再read()可能漏掉最后几行。这不是锁的问题,是并发读写一致性问题。
安全做法是:
- 避免用
mmap读正在被追加的文件,容易映射到旧长度 - 改用
os.stat().st_size动态获取当前大小,再read(),但注意两次系统调用间仍可能有写入 - 对日志类文件,用
inotify(Linux)或fsevents(macOS)监听IN_MODIFY事件,比轮询靠谱
真正难处理的永远不是“能不能打开”,而是“打开后读到的数据是否可信”。Windows锁让你打不开,Unix不锁却让你读不准——两边坑不一样,别拿同一套逻辑硬套。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











