asyncio的学习
协程
什么是协程?
又称为微进程,是一种用户态内的上下文切换技术。简而言之,其实就是通过一个线程实现代码块相互切换执行。实现协程的几种方法:
- greenlet,早期的模块
- yield关键字
- asyncio装饰器
- async、await关键字
协程的意义
在一个线程中,如果遇到IO等待时间,线程将利用空闲的时间再去干其他的事。
异步编程
事件循环
理解为一个死循环,去检测并执行某些代码。协程函数和协程对象
协程函数,定义函数时候async def 函数名
协程对象,执行协程函数()得到的就是协程对象。
注意:执行协程函数创建协程对象, 函数内部代码不会执行。所以需要协程对象和事件循环搭配运行。await
await 可等待对象 (协程对象、Future、Task对象 、 IO等待)
遇到IO操作挂起当前协程/任务(,等待IO操作完成之后继续往下执行。当前协程挂起时,事件循环可以去执行其他协程(任务)。Task对象
在事件循环当中添加多个任务的。
示例:
图中有三个任务在事件循环里,一个是main,这个是最先执行的,然后运行了这个main,里面添加了两个任务task1、task2当遇到await时,挂起当前线程执行task1,输出一个1,然后task1内部有一个await asynicio.sleep,这里有个await然后挂起,执行task2,也执行到await asynicio.sleep时继续挂起,此时等待task1里的await执行完毕之后继续向下执行,然后task2里的await也执行完毕之后继续向下执行,当这两个任务执行完毕之后继续向下顺序执行main函数里的。但是我们平时的话用的比较多的是这种:
1 |
|
或是这种
- asyncio.Future对象
Future objects are used to bridge low-level callback-based code with high-level async/await code.
Task继承Future, Task对象内部await结果的处理基于Future对象来的。
- concurrent.futures.Future对象
当某个第三方库不支持协程时可以考虑通过图中这种方式把对象变成Future对象
实例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17import asyncio
import requests
async def download_something(url):
loop = asyncio.get_event_loop()
be_future = loop.run_in_executor(None, requests.get, url)
response = await be_future
print(response.text)
if __name__ == '__main__':
urls = ['http://www.baidu.com', 'http://www.baidu.com', 'http://www.baidu.com']
tasks = [download_something(url) for url in urls]
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(tasks))
异步迭代器
实现aiter()方法的对象,__anext__必须返回一个awaitable对象,async_for会处理异步迭代器的__anext__方法返回的可等待对象,直到引发一个StopAsyncIteration异常。有PEP492引入。
什么是异步可迭代对象
可在async for语句中被使用的对象。必须通过它的aiter()方法返回一个asychronous iterator。由PEP492引入。
async for的代码必须写在async函数内
备注:async for一般用于想要获取其入口迭代对象,想循环获取其每一个值的时候会用到。
示例:
1 | import asyncio |
异步上下文管理器
此种对象通过定义aenter()和aexit()方法来对async with语句中的环境进行控制。由PEP 492引入。
该用处在于操作之前要打开什么,操作完之后在进行关闭
示例:
1 | import asyncio |
uvloop
这个是asyncio的事件循环的替代方案。事件循环 > 默认asyncio的事件循环。
一般使用都是:
1 | import asyncio |
大示例1——redis异步操作
在使用python代码操作redis时,链接、操作、断开都是网络I/O。
这里使用aioredis:
1 | import asyncio |
大示例2——异步MySQL
这里使用aiomysql
1 | import asyncio |
大示例3——FastAPI框架
安卓FastAPI
1 | pip install fastapi |
示例:
1 | import uvicorn |
大示例4——爬虫
使用aiohttp
1 | import aiohttp |