为什么要讲?
异步非阻塞、asyncio
tornado ,fastapi,django 3.x asgi、aiohttp都在异步> 提升性能

协程不是计算机提供,是程序员人为创造的。

协程(Coroutine),也可以被称为微线程,是一种用户态内的上下文切换技术。简而言之,其实就是通过一个线程实现代码块相互切换执行。例如:

  1. def funcl():
  2. print(1)
  3. ...
  4. print(2)
  5. def func2():
  6. print(3)
  7. ...
  8. print(4)
  9. fanc1
  10. func2

实现协程

有这么几种方法

  • greenlet,早期模块
  • yield关键字
  • asyncio装饰器(py3.4)
  • async、await关键字(py35)

greenlet实现协程

image.png

yield关键字 (了解)

image.png
如果一个函数里存在yield,被认为是一个生成器函数

asyncio 官方内置

python3.4及之后的版本。
image.png
写了一个装饰器
协程函数必须通过特殊写法执行。
注意:遇到IO阻塞会自动切换,(例如网络IO请求:下载一张图片 )

async、await关键字 (推荐)

python3.5及以后的版本。
不用装饰器了!
image.png

其他并行

executor = concurrent.futures.ThreadPoolExecutor()

executor.submit(func)
executor.shutdown()

多进程 concurrent 线程/进程异步

executor = concurrent.futures.ProcessPoolExecutor
https://www.yuque.com/docs/share/bb76f22f-47a2-4315-b0e0-4afa31df8d2a?# 《w220321: 并行脚本加速》

协程意义

在一个线程中如果遇到IO等待时间,线程不会傻傻等,利用空闲的时候再去干点其他事。

asyncio异步编程

事件循环

理解成为一个死循环,去检测并执行某些代码:
image.png

  1. import asyncio
  2. # 生成或获取一个事件循环
  3. loop=asyncio.get_event_loop()
  4. # 将任务放到“任务列表”
  5. loop.run_until_complete(asyncio.wait(tasks))|

快速上手

协程函数,定义函数时,async def 函数名;
协程对象,执行 协程函数() 得到的协程对象。

  1. async def func():
  2. pass
  3. result = func()

注意:执行协程函数创建协程对象,函数内部代码不会执行。

  1. import asyncio
  2. async def func():
  3. print("快来吧")
  4. result = func()
  5. # loop = asyncio.get_event_loop()
  6. # loop.run_until_complete(result)
  7. asyncio.run(result) # python3.7

await关键字

await + 可等待的对象 (协程对象、Future、Task对象 -》IO等待(先理解))

示例一:

  1. import asyncio
  2. async def func():
  3. print("来玩呀")
  4. response = await asyncio.sleep(2)
  5. print("over", response)
  6. asyncio.run(func())

示例二:
image.png

示例三:
一个协程函数可以有多个await
image.png
await就是等待对象的值得到结果之后在继续向下走。

Task对象

image.png
白话:在事件循环中添加多个任务的。
image.png

示例一:
image.png

示例二:

await返回一个元组,2个值,
done是一个集合,
pending,
image.png

async.run 等价于 时间循环创建+加列表

示例三:
错误:task里会立即加入事件循环,所以错
image.png

改进:
image.png

Future对象

底层、不常用。
task的基类。
image.png
_state
Task基础Future,Task对象内部await结果的处理基于Future对象来的。

示例一:
image.png
会一直等,除非赋值了

示例二:
image.png

concurrent.future.Future对象

使用线程池、进程池实现异步操作时用到的对象。
image.png

交叉使用

以后写代码可能会存在交叉时间。例如:crm项目80%都是基于协程异步编程+MySQL(不支持)【线程、进程做异步编程】

通过使用线程池或进程池使第三方模块能够异步编程,进而可以和协程异步编程一起完成项目。
image.png

案例:asyncio + 不支持异步的模块

image.png

asyncio异步迭代器

image.png
image.png
async for得写在协程函数内。

asyncio 异步上下文管理

image.png
支持async with ,也得写在协程函数里。 打开、关闭
image.png

uvloop 内部用了 这个快

是asyncio的事件循环的替代方案。事件循环效率 > 默认的asyncio的事件循环。
pip install uvloop

在进行asyncio编程时,加入2行代码:

  1. import uvloop
  2. asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())

image.png

实战案例

异步redis

在通过python代码操作redis时,链接/操作/断开都是网络IO。