关于python的多进程的一些细节
不同平台的区别
在 windows平台,python是使用spawn方式创建子进程,即导入当前的脚本作为module运行。在linux平台,则是以fork的方式创建子进程,父进程会拷贝当前的进程信息给子进程,子进程和父进程在异步继续执行。
这两种方式的不同,会导致我们在写代码时需要注意一些细节,对于spawn方式,由于子进程是重新导入一份脚本,所以创建子进程之前的代码也有可能被子进程执行,导致子进程又创建子进程,会出错。我们需要加入if name == 'main’来规避这种意外,即将只希望主进程执行的代码放在条件判断后,因为是导入模块,子进程并不会执行条件判断后的代码。而fork方式则不会产生这种情况,子进程会继续沿着主进程的进度往下执行。
使用multiprocessing创建多进程
在python中提供了multiprocessing类来创建多进程,可以一个一个地创建,即使用mp.Process(func,args),也可以使用进程池,mp.Pool来创建进程,调用pool的apply_async方法,这是异步创建,多个子进程会并发,而不是像apply的串行阻塞,在进程池加入任务后,利用close方法关闭进程池,再调用join方法阻塞主进程。
考虑到第一点,在Linux下,multiprocessing是默认fork方式,而我们可以使用mp.set_start_method(‘spawn’)来更改创建方式,两者不同如下面简单示例所示:
第一种情况,默认fork:
第二种情况,改为spawn:
可以看出,spawn方式下的子进程会再次执行main判断之外的可执行代码,这点要注意,尤其是windows系统。
使用multiprocessing多进程共享数据
由于不像多线程,数据是共享的,对于多进程,在创建子进程时,主进程会拷贝一份进程资源给子进程,这就造成了数据之间的独立,给我们维护一个多进程共享的数据库造成了麻烦。不过Mulprocessing库引入了一些共享的数据类型,我们可以使用,比如manager,manager可以包含很多数据类型,比如list,dict等。