协程是操作系统不可见的
什么是协程?
第三方模块
代码:
#方式一: import gevent def func(): #所有带有IO操作的内容都写在函数里,然后提交function print('start func') gevent.sleep(1) print('end func') g1=gevent.spawn(func) g2=gevent.spawn(func) g3=gevent.spawn(func) # gevent.sleep(2) # g1.join() #一直阻塞,直到协程g1任务执行结束 # g2.join() # g3.join() gevent.joinall([g1,g2,g3]) #方式二 ********* from gevent import monkey monkey.patch_all() #此两句必须写在所有导入模块的最上面,否则报错 import gevent import time def func(): #所有带有IO操作的内容都写在函数里,然后提交function print('start func') time.sleep(1) print('end func') g1=gevent.spawn(func) g2=gevent.spawn(func) g3=gevent.spawn(func) time.sleep(2) # g1.join() #一直阻塞,直到协程g1任务执行结束 # g2.join() # g3.join() # gevent.joinall([g1,g2,g3])
基于gevent协程实现Socket的并发
server
from gevent import monkey monkey.patch_all() import gevent import socket sk=socket.socket() sk.bind(('127.0.0.1',1235)) sk.listen() def func(conn): while True: msg=conn.recv(1024).decode('utf-8') MSG=msg.upper() conn.send(MSG.encode('utf-8')) while True: conn,addr=sk.accept() gevent.spawn(func,conn) #spawn开启任务
client
import socket sk=socket.socket() sk.connect(('127.0.0.1',1235)) while True: ret=input('请输入:') sk.send(ret.encode('utf-8')) mag=sk.recv(1024).decode('utf-8') print(mag)
原生的内置模块
asyncio,利用了底层模块(yield)完成切换 + 自动规避IO的功能
aiohttp模块:基于asyncio实现的,用来做并发的爬虫
sanic异步的轻量级的Web框架中,基于asyncio实现的
代码
import asyncio async def func(name): ''' await 可能会发生阻塞的方法 await关键字必须写在async函数里面 ''' print('start',name) await asyncio.sleep(1) print('end') loop=asyncio.get_event_loop() # loop.run_until_complete(func('xiaotong')) #调用一次 loop.run_until_complete(asyncio.wait([func('xiaotong'),func('minmin')])) #调用多次
生成器(Yield)中遇到yield的时候会直接切到函数外面,等到在此调用next的时候在执行下面的代码
代码
import time def sleep(n): print('start sleep') yield time.time()+n print('end sleep') def func(n): print('start') g=sleep(n) yield from g # yield from 相当于 await print('end') g1=func(1) g2=func(1.1) def run_until_complete(g1,g2): #run_until_complete就相当于run_until_complete ret1=next(g1) #睡完的时间 ret2=next(g2) #睡完的时间 ret_list={ret1:g1,ret2:g2} while ret_list: min_time=min(ret_list) #获取字典中睡眠最小的值 time.sleep(min_time-time.time()) try: next(ret_list[min_time]) #睡眠过后再次调用next except StopIteration:pass del ret_list[min_time] run_until_complete(g1,g2) #得:start start sleep start start sleep end sleep end end sleep end