从零开始的Python学习Episode 23——进程
---恢复内容开始---
进程
由于gil的存在,python中的多线程其实并不是真正的多线程,如果想要充分地使用多核cpu的资源,在python中大部分情况需要使用多进程。python提供了非常好用的多进程包multiprocessing,只需要定义一个函数,python会完成其他所有事情。借助这个包,可以轻松完成从单进程到并发执行的转换。multiprocessing支持子进程、通信和共享数据、执行不同形式的同步,提供了process、queue、pipe、lock等组件。
multiprocessing包是python中的多进程管理包。与threading.thread类似,它可以利用multiprocessing.process对象来创建一个进程。该进程可以运行在python程序内部编写的函数。该process对象与thread对象的用法相同,也有start(), run(), join()的方法。此外multiprocessing包中也有lock/event/semaphore/condition类 (这些对象可以像多线程那样,通过参数传递给各个进程),用以同步进程,其用法与threading包中的同名类一致。所以,multiprocessing的很大一部份与threading使用同一套api,只不过换到了多进程的情境。
创建进程的两种方法
调用内置的方法
from multiprocessing import process import time def fun(name): print(name+' is running') time.sleep(2) print(name+' end') if __name__ == '__main__': pro = process(target=fun,args=('no1',)) pro.start()
自定义类
from multiprocessing import process import os class myprocess(process): def __init__(self,name): process.__init__(self) self.name = name def run(self): print(os.getpid()) print(self.name+' is running') if __name__=='__main__': p1 = myprocess('1') p2=myprocess('2') p3=myprocess('3') p1.start() p2.start() p3.start()
注意:在运行的时候要在main里面运行,因为子进程是通过导入模块的方式拿到父进程的代码,如果没有main会一直开启子进程,而子进程的申请是需要开辟内存以及申请pid等的。
进程间通讯
队列queue()
使用方法跟threading里的queue类似,但是不同进程间内存是不共享的,所以要用下面的方法
from multiprocessing import process, queue def f(q,n): q.put('hello') def f1(q): print(q.get()) if __name__ == '__main__': q = queue() for i in range(2): p = process(target=f, args=(q,i)) p.start() tp1 = process(target=f1,args=(q,)) tp2 = process(target=f1, args=(q,)) tp3 = process(target=f1, args=(q,)) tp1.start() tp2.start()
要传入一个公共的queue来保证是同一个队列。
管道pipes
pipe()返回两个值(conn1,conn2),作为通讯的两个端。通过设置duplex参数来设置两个端口的功能,如果duplex参数为true(默认值),那么这个管道是全双工模式,也就是说conn1和conn2均可收发。duplex为false,conn1只负责接受消息,conn2只负责发送消息。
from multiprocessing import process, pipe def s(conn): conn.send('hello, how do you do') conn.close() def r(conn): print(conn.recv()) if __name__ == '__main__': conn1, conn2 = pipe() p1 = process(target=s, args=(conn1,)) p2 = process(target=r, args=(conn2,)) p1.start() p2.start()
managers实现进程之间的数据共享
manager支持 list
, dict
, namespace
, lock
, rlock
, semaphore
, boundedsemaphore
, condition
, event
, barrier
, queue
, value,
array等类型的共享
from multiprocessing import process, manager def f(d, l,n): d[n] = '1' d['2'] = 2 d[0.25] = none l.append(n) print(l) if __name__ == '__main__': with manager() as manager: d = manager.dict() l = manager.list(range(5)) p_list = [] for i in range(10): p = process(target=f, args=(d, l,i)) p.start() p_list.append(p) for res in p_list: res.join() print(d) print(l)
待续
推荐阅读
-
从零开始的Python学习Episode 6——字符串操作
-
从零开始的Python学习Episode 16——模块
-
从零开始的Python学习Episode 17——序列化
-
从零开始学习Python中的函数参数
-
从零开始的Python学习Episode 18——面向对象(1)
-
从零开始的Python学习Episode 1
-
从零开始的Python学习Episode 19——面向对象(2)
-
从零开始的Python学习Episode 12——迭代器&生成器
-
从零开始的Python学习Episode 7——文件基本操作
-
机器学习算法(23)python实现基于密度的有噪声的空间聚类应用(DBSCAN)