1、python 实现多进程
- 在unix/linux下python提供了一个fork()函数进行系统调用,fork()函数调用1次,会返回2次,因为操作系统自动把当前进程复制了一份,然后分别在父进程和子进程内返回。子进程永远返回0,而父进程返回子进程的id。子进程可以通过调用getppid()函数就可以看到父进程的id
import os
print 'Process (%s) start ...' % os.getpid()
pid = os.fork()
if pid == 0:
print 'i am child process (%s) and my parent is %s.' % (os.getpid(),os.getppid())
else:
print 'i (%s) just created a child process (%s).' % (os.getpid(),pid)
- 在win下没有fork调用,所以python提供了multiprocessing模块,实现跨平台版本的多进程模块。
from multiprocessing import Process
import os
def run_proc(nmae):
print 'Run child process %s.' % (nmae,os.getpid())
if __name__ == '__main__':
print 'Parent process %s.' % os.getpid()
p = Process(target = run_proc,arg = ('test',))
print 'Process will start .'
p.start()
p.join()
print 'Process end.'
注:
1、multiprocessing模块提供一个process类来代表一个进程对象;创建子进程时,只需要创建一个process实例,传入一个执行函数和函数的参数,最后用start()方法启动就可以了。
2、join()方法可以等待子进程结束后再继续往下运行,通常用于进程间的同步。
- 如果需要启动大量的子进程,可以用进程池的方式批量创建子进程:
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,arg = (i,))
print 'Waiting for all subprocesses done...'
p.close()
p.join()
print 'All subprocesses done.'
注:
Pool的默认大小是CPU的核数
- 进程间通讯
from multiprocessing import Process ,Queue
import os,time,random
def write(q):
for value in ['A','B','C']:
print 'Put %s to queue...' % value
q.put(value)
time.sleep(random.random())
def read(q):
while True :
value = q.get(True)
print 'Get %s from queue.' % value
if __name__ == '__main__':
q = Queue()
pw = Process(target = write,args = (q,))
pr = Process(target = read,args = (q,))
pw.start()
pr.start()
pw.join()
pr.terminate()
注:
>1、Python的multiprocessing模块包装了底层的机制,提供了Queue、Pipes等多种方式来交换数据。
>2、在Unix/Linux下,multiprocessing模块封装了fork()调用,使我们不需要关注fork()的细节。由于Windows没有fork调用,因此,multiprocessing需要“模拟”出fork的效果,父进程所有Python对象都必须通过pickle序列化再传到子进程去,所有,如果multiprocessing在Windows下调用失败了,要先考虑是不是pickle失败了。