Python之多进程
1、操作系统相关
Unix/Linux操作系统中提供了一个fork'()函数,调用一次返回两次,因为操作系统自动把当前进程(父进程)复制了一份(子进程),然后分别在父进程和子进程中返回。
子进程中永远返回0,父进程中返回子进程的ID,这样一个父进程可以fork出很多的子进程,所以父进程要几下每一个子进程的ID,而子进程需要调用getppid()就可拿到父进程的ID。
Python的os模块封装了常见的系统调用,其中包括fork,可以在Python中轻松创建子进程。
注:Windows没有fork调用。
2、multiprocessing
from multiprocessing import Process import os # 子进程要执行的代码 def run_proc(name): print ('Run child process %s (%s)...' % (name, os.getpid())) if __name__=='__main__': print ('Parent process %s.' % os.getpid()) p = Process(target=run_proc, args=('test',)) print ('Process will start.') p.start() p.join() print ('Process end.')
创建子进程时,只需要闯入一个执行函数和函数的参数,创建一个Process实例,调用start()启动。
2、Pool
如果要启动大量的子进程,可以用线程池的方式批量的创建子进程
from multiprocessing import Pool import os, time, random def long_time_task(name): print ('Run task %s (%s)...' % (name, os.getpid())) start = time.time() time.sleep(random.random() * 3) end = time.time() print ('Task %s runs %0.2f seconds.' % (name, (end - start)))
if __name__=='__main__': print ('Parent process %s.' % os.getpid()) p = Pool() for i in range(5): p.apply_async(long_time_task, args=(i,)) print 'Waiting for all subprocesses done...' p.close() p.join() print ('All subprocesses done.')
Pool对象调用join会等待所有子进程执行完毕,调用join之前必须调用close。调用close之后就不能再添加新的Process了。
Pool的默认大小是4,所以每次只能同时跑4个进程只有等前面的某个 进程执行完才会执行第五个,这是Pool刻意设计的并不是操作系统的限制。
p=Pool(5) 则同时可以跑5个进程。
4、进程间的通信
Python的multiprocessing模块提供了底层机制,提供了Queue,Pipes等当方式交换数据。
if __name__=='__main__': # 父进程创建Queue,并传给各个子进程: q = Queue() pw = Process(target=write, args=(q,)) pr = Process(target=read, args=(q,)) # 启动子进程pw,写入: pw.start() # 启动子进程pr,读取: pr.start() # 等待pw结束: pw.join() # pr进程里是死循环,无法等待其结束,只能强行终止: pr.terminate()