Python文件锁需用flock或portalocker等系统级机制,因open()和with不提供并发保护,多进程写入会导致覆盖或错乱;推荐portalocker跨平台加锁,或用临时文件+os.replace实现原子写入。

Python中实现文件锁,核心是避免多个进程或线程同时写入同一文件导致数据错乱、覆盖或损坏。单线程内用普通变量或 threading.Lock 即可,但跨进程必须依赖操作系统级的锁机制,比如 flock(Unix/Linux/macOS)或 msvcrt.locking(Windows),更通用稳妥的做法是使用第三方库 portalocker 或标准库中的 threading.Lock + 进程间协调(如文件信号量)。
为什么不能只靠 open() 和 with 语句?
with open(..., 'w') 只保证当前 Python 对象在作用域内不被意外关闭,完全不提供任何并发保护。两个进程同时执行该语句,会各自打开文件并写入,后写入者大概率覆盖前者的全部内容——尤其当写入非原子(比如分多次 write())时,还可能出现内容交错、截断、乱码等现象。
推荐方案:用 portalocker 实现跨平台文件锁
portalocker 封装了底层系统调用,自动适配不同操作系统,API 简洁可靠,是生产环境首选。
- 安装:pip install portalocker
- 基本写入加锁示例:
import portalocker import jsondef safe_write_json(filepath, data): with open(filepath, 'w') as f:
排他锁(LOCK_EX),阻塞直到获得锁
portalocker.lock(f, portalocker.LOCK_EX) try: json.dump(data, f) f.flush() # 确保内容真正写入磁盘 finally: portalocker.unlock(f) # 显式解锁更安全立即学习“Python免费学习笔记(深入)”;
易语言入门教程 CHM版下载易语言入门教程 CHM,介绍易语言的系统基本数据类型、常量表、运算符、位运算命令以及易语言支持库方面的问题,易语言所编写的程序运行时都需要加载易语言的支持库文件.表面上易语言的非独立编译所生成的EXE程序体积小巧.但事实上若想把软件发布出去给别人的电脑上使用.非独立编译将面临很多的问题.所以实际应用时应全部进行独立编译。
进阶注意点:锁的粒度与生命周期
文件锁绑定在「文件描述符」上,不是文件路径。这意味着:
- 同一个进程内重复 open 同一路径 → 得到不同 fd → 需分别加锁;
- fork 子进程会继承父进程的 fd 和锁状态,子进程退出可能自动释放锁(行为因系统而异);
- 程序崩溃未 unlock?多数系统会在 fd 关闭时自动释放,但为防万一,建议配合
try/finally或上下文管理器(portalocker.Lock类已支持); - 若只需防止并发写入,读操作通常无需加锁(除非你要求“读时文件不能被改”)。
替代方案对比:flock vs. 临时文件原子重命名
对于日志类追加写入,flock 足够;但对需要「全量替换」的场景(如保存配置、缓存),更健壮的做法是:
- 写入临时文件(如
config.json.tmp); - 调用
os.replace()(Python 3.3+,原子性跨平台)重命名为目标名; - 即使无锁,也能避免写到一半被读取到脏数据。
这种方式本质是用「原子重命名」代替「文件锁」,适合写一次读多次、不要求实时强一致的场景。










