
协程不是计算机提供的机制,是程序员人为定义的。
协程被称为微线程,是一种用户态的上下文切换的技术。
简而言之就是通过一个线程实现代码块相互切换运行。
协程的意义线程执行任务时 遇到IO耗时 *** 作 不会再等待 而是去执行其他工作
二 实现协程的方法 1 greenlet实现协程from greenlet import greenlet
def fun():
print(111)
gr2.switch()
print(222)
gr2.switch()
def fun1():
print(33)
gr1.switch()
print(44)
gr1 = greenlet(fun)
gr2 = greenlet(fun1)
gr1.switch()
2 yield方法
# 创建生成器函数
def fun1():
yield 1
yield from fun2()
yield 2
def fun2():
yield 3
yield 4
f = fun1()
for item in f:
print(item)
3 asyncio.coroutine方法 因为用的3.9版本 所以不支持 我就不写了
4async&awit关键字方法(推荐)
python3.5版本后才可以使用
import asyncio
async def func1():
print(1)
# 网络IO请求 下载一张图片
await asyncio.sleep(2) # 遇到类似IO耗时 *** 作 自动切换到task中的其他任务
print(2)
async def func2():
print(33)
# 网络IO请求 下载一张图片
await asyncio.sleep(2) # 遇到IO耗时 *** 作,自动化切换到task中的其他 *** 作
print(444)
tasks = [asyncio.ensure_future(func2()),
asyncio.ensure_future(func1())]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
按顺序执行 遇到耗时 *** 作时执行其他任务
结果 33 1 444 2三 异步编程 事件循环
理解成一个死循环,去检测并执行某些代码
# 伪代码
任务列表=[任务1,任务2,任务3]
while true:
可执行的任务列表(比如IO请求完毕剩下其余逻辑),已完成的任务列表(任务代码全部完成) = 去任务列表中检查所有的任务 将可执行和已完成的任务返回
for 可执行任务 in 可执行的任务列表:
执行可执行的任务
for 已完成的任务 in 已完成的任务列表:
在任务列表中移除已经完成的任务
如果任务列表中的任务都已完成 则终止循环
import asyncio #去生成或获取一个事件循环 loop = asynio.get_event_loop() #将任务放到任务列表 (在任务列表中自动检测任务状态) loop.run_util_complete(任务)协程函数
函数名前面有async 关键字的函数
协程对象 执行协程函数得到的对象
# 协程函数
async def func():
print (111)
# 协程对象
result = func()
协程对象的内部代码不会执行
如果要执行 需要交给事件循环来处理
import asyncio
async def func():
print(111)
result = func()
# loop = asyncio,get_event_loop()
# loop.run_until_complete(result)
asyncio.run(result) # python3.7以后
await
await+可等待对象(协程对象,Future,Task对象-》IO等待)
import asyncio
async def func():
print ("xxx")
response = await asyncio.sleep(2)
print("结束",response)
asyncio.run(func())
await 就是等待对象的值得到结果之后再继续向下走
Task对象在事件循环中添加多个任务的。
示例1
import asyncio
async def func():
print(111)
await asyncio.sleep(2)
print(222)
async def main():
print("main开始")
# 创建task任务 并将task 任务添加到事件循环
task1 = asyncio.create_task(func())
task2 = asyncio.create_task(func())
ret1 = await task1
ret2 = await task2
print(ret1, ret2)
asyncio.run(main())
示例2
import asyncio
async def func():
print(111)
await asyncio.sleep(2)
print(222)
async def main():
print("main开始")
# 创建task任务 并将task 任务添加到事件循环
task1 = asyncio.create_task(func(),name="task1")
task2 = asyncio.create_task(func(),name = "task2")
task_list = [task1, task2]
# 返回值都放在done集合中,pending 执行过程中部分返回值放在pending中
done, pending = await asyncio.wait(task_list)
print(done)
asyncio.run(main())
asyncio.Future对象(了解)
task对象基于future future如果不被赋值 将一直执行不会终止 但task一般绑定一个函数,函数执行完自动赋值 也自动终止。
Concurrent.future.Future对象使用线程池 进程池实现异步时使用的对象
如果做异步编程时 遇到了某个第三方模块不支持协程时 使用下面这种方式
异步和非异步结合案例
asyncio异步迭代器class Reader(object):
"""自定义异步迭代器(同是也是异步可迭代对象)"""
def __init__(self):
self.count = 0
async def readline(self):
self.count +=1
if self.count ==100:
return None
return self.count
def__aiter__self(self):
return self
async def __anext__(self):
val = await self.readline()
if val == None:
raise StopAsyncIteration
return val
async def func():
obj = Reader()
#async for 循环只能在异步函数中使用
async for item in obj:
print(item)
asyncio.run(func())
asyncio 异步上下文管理器
uvloop
是asyncio循环的替代方案,事件循环>默认的asyncio的事件循环
效率提升至少一倍
django3和fastapi内部就是使用的uvloop 所以快 支持 异步
实战案例 异步 *** 作redis在使用代码 *** 作redis时,链接、 *** 作、断开都是网络IO
同时使用两台服务器的redis 在连接第一台服务器的时候去做连接第二台服务器的任务,
异步 *** 作mysqlpip install aiomysql
FASTAPI框架示例爬虫示例:
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)