Python多进程间如何共享文件对象并实现读写同步避免竞态?
问题原因
你遇到的报错核心原因是:Python multiprocessing 队列在跨进程传递对象时,会先对对象执行pickle序列化操作,但已打开的文件句柄(_io.TextIOWrapper类型)不支持序列化,所以往队列里put文件对象时直接触发类型错误。
额外补充:即使绕过序列化限制,直接跨进程共享文件句柄也会出现预期外的问题,比如不同进程的文件缓冲区独立,写入内容会出现乱序、丢失等情况。
解决方案
- 方案1:子进程加锁后自行打开文件写入
这个方案改动最小,不需要调整现有结构,适合单文件写入场景。
from multiprocessing import Process, Lock def writeTofile(lock, i): print(f'some work by {i}') text = f" Process {i} -- " ans ="" for _ in range(10000): ans += text # 临界区:加锁后打开文件写入,写完立即关闭 lock.acquire() # 注意这里用a模式追加,每次打开会自动定位到文件末尾 with open("test.txt", mode = 'a') as file: file.write(ans) lock.release() print(f'updated by process {i}') def main(): lock = Lock() jobs = [] for i in range(4): process = Process(target = writeTofile, args = (lock, i)) jobs.append(process) process.start() for j in jobs: j.join() print('completed') if __name__ == "__main__": main()
- 方案2:生产者消费者模型(推荐用于大量文件读写场景)
你要处理大量JSON文件的话,更合理的架构是让工作进程只负责生成/处理要写入的内容,单独启动一个专属的写进程负责所有IO操作,不需要额外加锁,性能更高:
from multiprocessing import Queue, Process # 工作进程:负责处理数据,生成待写入内容 def worker(q, i): print(f'some work by {i}') text = f" Process {i} -- " ans ="" for _ in range(10000): ans += text # 把要写的内容丢到队列即可 q.put(ans) print(f'updated by process {i}') # 写进程:唯一负责写文件的进程,不需要加锁 def writer(q): with open("test.txt", mode = 'a') as file: while True: content = q.get() # 收到结束标记就退出 if content == 'done': break file.write(content) def main(): q = Queue() jobs = [] # 先启动写进程 write_process = Process(target=writer, args=(q,)) write_process.start() # 启动4个工作进程 for i in range(4): process = Process(target = worker, args = (q, i)) jobs.append(process) process.start() # 等待所有工作进程结束 for j in jobs: j.join() # 给写进程发结束标记 q.put('done') write_process.join() print('completed') if __name__ == "__main__": main()
额外提示:如果你是多个进程写不同的JSON文件,只要保证每个文件只有一个进程写入,就完全不需要加锁,性能会更好。
内容的提问来源于stack exchange,提问作者Akshay Singh
相关产品推荐
相关产品推荐

