多进程旧式写法
from multiprocessing import Pool def f(x): return x*x if __name__ == '__main__': p = Pool(5) print(p.map(f,[1,2,3]))
多进程新式写法
from multiprocessing import Process def run(num): print 'this is ',num for i in range(10): t = Process(target=run,args=(i,)) t.start()
多进程-父子进程
from multiprocessing import Process import os def info(title): print title print 'module name:',__name__ if hasattr(os,'getppid'): print 'parent process:',os.getppid() #获取父进程PID print 'process id:',os.getpid() #获取子进程PID def f(name): info('function f') #子进程调用info函数 print 'hello',name if __name__ == '__main__': info('main line') #父进程调用info函数 print '---------------' p = Process(target=f,args=('bob',)) p.start() p.join()
进程数据共享
from multiprocessing import Process li = [] def run(num): li.append(num) print 'say hi',li for i in range(10): t = Process(target=run,args=(i,)) t.start() print 'ending',li
进程各自持有一份数据,默认无法共享数据,要使进程间可以共享数据,则
#方法一,Array
from multiprocessing import Process,Array #创建一个只包含数字类型的一个数组/列表,并且个数不可变 temp = Array('i', [11,22,33,44]) def Foo(i): temp[i] = 100+i for item in temp: print i,'----->',item for i in range(2): p = Process(target=Foo,args=(i,)) p.start()
#方法二:manage.dict()共享数据
from multiprocessing import Process,Manager manage = Manager() dic = manage.dict() def Foo(i): dic[i] = 100+i print dic.values() for i in range(2): p = Process(target=Foo,args=(i,)) p.start() p.join()
#方法3,Queue
from multiprocessing import Process,Queue def f(q,n): q.put([n,'hello']) if __name__ == '__main__': q = Queue() for i in range(5): p = Process(target=f,args=(q,i)) p.start() while True: print q.get()
#方法4,Manager
from multiprocessing import Process,Manager def f(d,l): d[1] = '1' d['2'] = 2 d[0.25] = None l.reverse() #反向列表 if __name__ == '__main__': manager = Manager() d = manager.dict() #d = {} l = manager.list(range(10)) #l = [0,1,2,4,5,6,7,8,9] p = Process(target=f,args=(d,l)) p.start() p.join() print d print l
进程锁
from multiprocessing import Process, Array, RLock def Foo(lock,temp,i): """ 将第0个数加100 """ lock.acquire() #加锁 temp[0] = 100+i for item in temp: print i,'----->',item lock.release() #解锁 lock = RLock() temp = Array('i', [11, 22, 33, 44]) for i in range(20): p = Process(target=Foo,args=(lock,temp,i,)) p.start()
进程池
进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,如果进程池序列中没有可供使用的进进程,那么程序就会等待,直到进程池中有可用进程为止。
进程池中有两个方法:
- apply
- apply_async
from multiprocessing import Process,Pool import time def Foo(i): time.sleep(2) return i+100 def Bar(arg): print arg pool = Pool(5) #print pool.apply(Foo,(1,)) #print pool.apply_async(func =Foo, args=(1,)).get() for i in range(10): pool.apply_async(func=Foo, args=(i,),callback=Bar) print 'end' pool.close() pool.join()#进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。
from multiprocessing import Pool import time def f(x): print x*x #time.sleep(2) return x*x if __name__ == '__main__': pool = Pool(processes=2) #同时5个进程 res_list = [] for i in range(5): res = pool.apply_async(f,[i,]) #res = Process(target=f,args=[i,]) print '-----------',i res_list.append(res) for r in res_list: print 'res_list:',r.get()
协程
线程和进程的操作是由程序触发系统接口,最后的执行者是系统;协程的操作则是程序员。
协程存在的意义:对于多线程应用,CPU通过切片的方式来切换线程间的执行,线程切换时需要耗时(保存状态,下次继续)。协程,则只使用一个线程,在一个线程中规定某个代码块执行顺序。
协程的适用场景:当程序中存在大量不需要CPU的操作时(IO),适用于协程;
greenlet
#!/usr/bin/env python # -*- coding:utf-8 -*- from greenlet import greenlet def test1(): print 12 gr2.switch() print 34 gr2.switch() def test2(): print 56 gr1.switch() print 78 gr1 = greenlet(test1) gr2 = greenlet(test2) gr1.switch()
gevent
import gevent def foo(): print('Running in foo') gevent.sleep(0) print('Explicit context switch to foo again') def bar(): print('Explicit context to bar') gevent.sleep(0) print('Implicit context switch back to bar') gevent.joinall([ gevent.spawn(foo), gevent.spawn(bar), ])
遇到IO操作自动切换:
from gevent import monkey; monkey.patch_all() import gevent import urllib2 def f(url): print('GET: %s' % url) resp = urllib2.urlopen(url) data = resp.read() print('%d bytes received from %s.' % (len(data), url)) gevent.joinall([ gevent.spawn(f, 'https://www.python.org/'), gevent.spawn(f, 'https://www.yahoo.com/'), gevent.spawn(f, 'https://github.com/'), ])