Python中的多进程⼏个⼩问题总结
Python中的多进程⼏个⼩疑点总结
Python中的多进程⼏个⼩问题总结
问题初始
初始是想⽤Python进⾏⼀个多进程的处理,所需并⾏的函数中可能存在异常,需进⾏捕获,当出现异常时需要终⽌程序,停⽌所有的⼦进程。
例如:
def func():
try:
some_function()
except:
⾸先,我采⽤的是Python的multiprocessing包,⽤的是Pool进⾏简单处理
with multiprocessing.Pool(num_workers) as pool:
pool.map(func, arg_list)
当然,这⾥如果想传多个参数可以选择⽤zip函数。此时,如果没有异常,程序将正常运⾏,返回想要的结果。但产⽣异常时,如果没有设置timeout参数的话将会被永久挂起,并不会如我所想的那样在检测出异常时停⽌运⾏。
当然这⾥如果我们⼿动分配process的话会处理这个问题,不过在此我需要进⾏处理的List很长,所以还是选⽤了Pool的⽅式。并且在我这⾥的需求时需要将程序挂起运⾏,也就是⽤nohup,如此的话将永远被挂在后台,如果停⽌需要Kill每个进程,并且你并不会知道哪⾥让其产⽣了异常。
⾸先,我进⾏了查询,问题⼀:由于⼦进程的异常不会导致parant停⽌分配⼯作,不会影响其他⼦进程。
是it()是仅仅抛出⼀个异常,因此和其他的异常⼀样,不会导致程序真正的停⽌。
此时,如果选⽤os.exit()则在⼀定情况下可以推出,os.exit()是⼀个不进⾏cleanup的暴⼒退出⽅法,通常只有在特殊情况下才会使⽤。
问题⼆:map函数的机制。
关于multiprocessing.Pool与concurrent.ProcessPoolExcutor的区别
此时,我最开始的想法是去找⼀些其他的package,最后发现其实都是⼀样的东西,封装了multiprocessing的简单API⽽已。concurrent 就是multiprocessing的⼀个wrapper,虽然有⼀些细⼩的区别,但是基本上不影响使⽤。两个packages其实是在简单和功能的trade-off。这条路破灭。
map和imap
map和imap的机制是不同的。
map是将List分成⼏个chunk,然后将这些chunk分配给worker。map对于数据很多的时候将会消耗很多的内存,它是等待所有的⼦程序运⾏完成之后才会返回结果。
⽽imap不同,它并不是将List分成⼏个chunk,⽽是每次只分配给work⼀个任务,这样的话会⽐较慢,但是会没那么消耗内存,它最终返回的是⼀个带有结果的迭代器。imap是可以直接获得结果的,它并
不需要等待所有的结果完成,这就意味着我们可以让⼦进程变运⾏,我们边进⾏异常捕获。从⽽当发⽣异常时,结束pool。
我们的问题结局了,简单⽰例如下:
with multiprocessing.Pool as pool:
res = pool.imap(func, arg_list)
try:
res = list(res)
except:
rai
如此,我们就可以在异常发⽣的第⼀时间,捕获异常,然后退出Pool。
关于join()函数
其实join的函数并不是关联或者合并的意思,⽽是简单的意味着等待进程结束。当很多⼦进程处在休息的状态,或者我们停⽌之后,可以⽤join函数的⽅法将他们恢复⼯作。
简单记录⼀次查资料,希望有帮助,谢谢⼤家!