python multiprocess踩坑记录:在进程池multiprocess.Pool模块中使用锁Lock

it2023-07-05  70

python multiprocess踩坑记录:在进程池multiprocess.Pool模块中使用锁Lock

不使用Lock造成print重叠加锁遇到的问题使用Manager对其加锁

需求:开启多个独立运行的子进程(1k+),子进程中可能出现异常,但不知道报什么错,要求子进程出错不妨碍其他进程继续执行,结束之后能看到哪些进程出了错并整合成日志。

不使用Lock造成print重叠

下面是一个50%概率出现除0错误的进程

def raise_error(i): try: rand=random.randrange(0,2) ans=10/rand time.sleep(1) print(os.getpid(),':',i,'sucess result is',ans,'parent',os.getppid()) return ans except Exception as e: print(os.getpid(),':',i,'failed',e,'parent',os.getppid()) return -1

使用multiprocess.Pool模块调用,进程池大小为3,总共10个进程

if __name__ == '__main__': print('Parent process %s.' % os.getpid()) pool=multiprocessing.Pool(processes=3) for i in range(10): pool.apply_async(func=raise_error,args=(i,)) pool.close() pool.join() print('done')

有概率出现以下结果: 可以看到输出有重叠,原因在于三个进程同时往缓冲区string buffer中写数据造成stdout未按顺序输出(往相同total log中输出同理),所以需要对子进程中的print进行加锁

加锁遇到的问题

根据官方文档以及众多博客所写的进行加锁

def lock_raise_error(i,l): try: rand=random.randrange(0,2) ans=10/rand l.acquire()#加锁 print(os.getpid(),':',i,'sucess result is',ans) l.release() return ans except Exception as e: print(os.getpid(),'failed',e) return -1 if __name__ == '__main__': print('Parent process %s.' % os.getpid()) pool=multiprocessing.Pool(processes=3) lock=multiprocessing.Lock() for i in range(10): a=pool.apply_async(func=lock_raise_error,args=(i,lock)) pool.close() pool.join() print(a.successful()) print('done')

结果如下,并没有执行 一开始还以为是因为args里面元组出现问题,改成args=(i,lock,)之后依旧没有执行,原因大概在于官方文档和博文中都是用Process模块开启多线程,再使用Lock加锁,但Pool模块无法使用这种方法加锁

使用Manager对其加锁

参考https://blog.csdn.net/u013713010/article/details/53325438 的方法使用manager加锁

def lock_raise_error(i,l): try: rand=random.randrange(0,2) ans=10/rand time.sleep(1) l.acquire() print(os.getpid(),':',i,'sucess result is',ans) l.release() return ans except Exception as e: print(os.getpid(),'failed',e) return -1 if __name__ == '__main__': print('Parent process %s.' % os.getpid()) pool=multiprocessing.Pool(processes=3) lock=multiprocessing.Manager().Lock()#使用Manager加锁 for i in range(10): a=pool.apply_async(func=lock_raise_error,args=(i,lock)) pool.close() pool.join() print(a.successful()) print('done')

输出没有出现重叠现象,加锁成功,输出到total日志文件同理 与https://blog.csdn.net/u013713010/article/details/53325438不同的是,我在直接使用Lock而非Manage().Lock()时,并没有出现RuntimeError。 使用Pool时除了Lock需要在Manager中初始化还有Queue,Value等。

最新回复(0)