多进程
多进程:在多个CPU运行
多进程实现方式:函数式,继承式
multiprocessing模块:
multiprocessing模块用来开启子进程,并在子进程中执行我们定制的任务(比如函数)
multiprocessing模块的功能众多:支持子进程、通信和共享数据、
执行不同形式的同步,提供了Process、Queue、Pipe、Lock等组件。
需要再次强调的一点是:与线程不同,进程没有任何共享状态,进程修改的数据,改动仅限于该进程内。
Process类的
创建进程的类
Process([group [, target [, name [, args [, kwargs]]]]]),由该类实例化得到的对象,
表示一个子进程中的任务(尚未启动)
#函数式
import multiprocessing,time
def run(name):
time.sleep(5)
print("来了",name)
if __name__ == '__main__':
p1 = multiprocessing.Process(target=run,kwargs={"name":"老弟1"},name="l1")
p2 = multiprocessing.Process(target=run,kwargs={"name":"老弟2"},name="l2")
p3 = multiprocessing.Process(target=run,kwargs={"name":"老弟3"},name="l3")
p1.daemon = True
#print(p1.name)#进程名称
p1.start()
p2.start()
p3.start()
#p1.terminate()#强制终止进程
#print(p1.is_alive())
#time.sleep(6)
#print(p1.is_alive())
#p1.join(timeout=2)
#print("主线程结束")
p1.terminate()#关闭进程,不立刻关
print(p1.is_alive())
time.sleep(1)
print(p1.is_alive())
#继承式
import multiprocessing,time
class MyProcess(multiprocessing):
def __init__(self):
multiprocessing.Process.__init__(self)
def run(self):
print("来了老弟")
if __name__=="__main__":
p1 = MyProcess()
p2 = MyProcess()
p1.start()
p2.start()
全局解释器锁GIL
GIL导致线程不能利用多核优势
解决方案可以根据任务的类型来处理,如果是I/O密集型,则需要开多线程提高效率,
如果是计算密集型则需要多进程
锁(进程同步)
import multiprocessing,time
#lock = multiprocessing.Lock()
def work(name,lock):
lock.acquire()
with open("a.txt",mode="r+",encoding="utf8") as f:
c = int(f.read())
c -= 1
time.sleep(1)
print(name,c)
f.write(str(c))
lock.release()
if __name__ == '__main__':
lock = multiprocessing.Lock()
p1 = multiprocessing.Process(target=work,args=("p1",))
p2 = multiprocessing.Process(target=work,args=("p2",))
p3 = multiprocessing.Process(target=work,args=("p3",))
p1.start()
p2.start()
p3.start()
进程间通信(IPC)
方式一:队列(推荐使用)
import multiprocessing,time
def work(q):
if not q.empty():
print(q.get())
if __name__=="__main__":
q = multiprocessing.Queue(maxsize=3)
q.put(1)
q.put(2)
q.put(3)
# q.get()
# print(q.get())
p1 = multiprocessing.Process(target=work,args=(q,))
p2 = multiprocessing.Process(target=work, args=(q,))
p1.start()
p2.start()
方式二:管道
import multiprocessing
def jieshou(left,right):#左接收,右发送
#right.close()
while True:
print(left.recv())
left.send("你好")
def fasong(left,right):
#left.close()
while True:
right.send("我是被发送出去的数据")
print(right.recv())
if __name__=='__main__':
left,right = multiprocessing.Pipe()
p1 = multiprocessing.Process(target=jieshou,args=(left,right))
p2 = multiprocessing.Process(target=fasong, args=(left, right))
p1.start()
p2.start()
进程池
开多进程的目的是为了并发,如果有多核,通常有几个核就开几个进程,进程开启过多,效率反而会下降
当被操作对象数目不大时,可以直接利用multiprocessing中的Process动态成生多个进程,十几个还好,但如果是上百个,上千个目标,手动的去限制进程数量却又太过繁琐,此时可以发挥进程池的功效。
在利用Python进行系统管理的时候,特别是同时操作多个文件目录,或者远程控制多台主机,并行操作可以节约大量的时间。
创建进程池的类:
Pool([numprocess [,initializer [, initargs]]]):创建进程池
参数介绍:
numprocess:要创建的进程数,如果省略,将默认使用cpu_count()的值
initializer:是每个工作进程启动时要执行的可调用对象,默认为None
initargs:是要传给initializer的参数组