本节内容:
- 多进程
- 协程
- 事件驱动与SelectPollEpoll异步IO
1. 多进程
启动多个进程
进程中启进程
父进程与子进程
进程间通信
不同进程间内存是不共享的,要想实现两个进程间的数据交换,可以用以下方法:
a) queues

#!/usr/bin/env python # -*- coding:utf-8 -*- from multiprocessing import Process, Queue import queue import threading def f(qq): qq.put("hahaha123") if __name__ == '__main__': #q = queue.Queue() # 线程queue不能直接传给子进程 q = Queue() p = Process(target=f, args=(q,)) #p = threading.Thread(target=f, args=(q,)) p.start() print(q.get()) p.join()
父进程克隆了一个Queue,将克隆的Queue交给了子进程,当一个Queue对数据进行修改时,会将修改后的Queue数据序列化到某一位置,另一个Queue会从这个位置反序列化获取数据,实现进程间的通信
b) Pipes

#!/usr/bin/env python # -*- coding:utf-8 -*- from multiprocessing import Process, Pipe def f(conn): conn.send("qqqqqq") conn.send("qqqqqq2") print("from parent:", conn.recv()) conn.close() if __name__ == '__main__': parent_conn, chile_conn = Pipe() p = Process(target=f, args=(chile_conn,)) p.start() print(parent_conn.recv()) print(parent_conn.recv()) parent_conn.send("hehehhe") p.join()
c) Managers 实现进程间数据的共享,可以同时修改,而不是数据的传递

#!/usr/bin/env python # -*- coding:utf-8 -*- # Author: zhoujunlong from multiprocessing import Process, Manager import os def f(d, l): d[os.getpid()] = os.getpid() l.append(os.getpid()) print(l) if __name__ == '__main__': with Manager() as manager: d = manager.dict() # 生成一个字典可在多个进程间共享和传递 l = manager.list()# 生成一个列表可在多个进程间共享和传递 p_list = [] for i in range(10): p = Process(target=f, args=(d, l,)) p.start() p_list.append(p) for res in p_list:# 等待结果 res.join() print(d) print(l)
进程同步

#!/usr/bin/env python # -*- coding:utf-8 -*- from multiprocessing import Process,Lock def f(l, i): l.acquire() print("hello world", i) l.release() if __name__ == '__main__': lock = Lock() for num in range(10): Process(target=f, args=(lock, num)).start()
进程池(生产中常用)

#!/usr/bin/env python # -*- coding:utf-8 -*- from multiprocessing import Process, Pool, freeze_support import time, os def Foo(i): time.sleep(2) print("in process ", os.getpid()) return i def Bar(args): print("--->", args, os.getpid()) if __name__ == '__main__': #freeze_support() pool = Pool(processes=5) print("main_process:", os.getpid()) for i in range(10): #pool.apply(func=Foo, args=(i,)) #pool.apply_async(func=Foo, args=(i,)) pool.apply_async(func=Foo, args=(i,),callback=Bar) print('end') pool.close() pool.join() #进程池中进程执行完毕后再关闭,注释后程序不等进程执行我那后就直接关闭了
2. 协程
协程,微线程
协程的好处:
- 无需线程上下文切换的开销
- 无需原子操作的锁定及同步的开销
- 方便切换控制流,简化编程模型
- 高并发+高扩展+低成本(一个cpu可支持上万个协程)
缺点:
- 无法利用多核资源,需要和进程配合才能运行在多CPU上
- 运行阻塞(blocking)操作会阻塞整个程序
通过yield实现简单的协程(单线程实现多并发效果):

#!/usr/bin/env python # -*- coding:utf-8 -*- def consumer(name): print("----->starting") while True: new_baozi = yield print("[%s] is eating baozi %s" % (name, new_baozi)) def producer(): r = con.__next__() r = con2.__next__() n = 0 while n < 5: n += 1 print("