Python笔记(十八):协程asyncio
(一)asyncio
1、asyncio 用async 修饰词来声明异步函数
2、asyncio.create_task(异步函数)来创建任务
3、通过await asyncio.gather(任务)来执行任务
4、通过asyncio.run(函数)来触发运行
5、一个比较好的方式是asyncio.run(main())作为程序入口,在程序运行周期内,只调用一次asyncio.run()
例如:请求5次这个url https://www.java.com/zh_CN/
用协程是3.8s,不用协程9.2s。当然这个时间对比可能不是非常准确,因为请求过程还受其他因素影响,不过应该能大致说明问题。
1 import datetime 2 3 import asyncio 4 import aiohttp 5 6 header = { 7 "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36", 8 "Host":"c.oracleinfinity.io", 9 "Accept-Encoding":"gzip, deflate, br", 10 "accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" 11 } 12 async def fetch_content(url): 13 async with aiohttp.ClientSession( 14 headers=header,connector=aiohttp.TCPConnector(ssl=False) 15 ) as session: 16 async with session.get(url) as response: 17 return await response.text() 18 19 async def main(): 20 url = "https://www.java.com/zh_CN/" 21 urls = [url for i in range(5)] 22 tasks = [asyncio.create_task(fetch_content(url)) for url in urls] 23 pages = await asyncio.gather(*tasks) #*表示解包列表,解包字典则用2个星号** 24 25 26 start_time = datetime.datetime.now() 27 print(start_time) 28 asyncio.run(main()) 29 end_time = datetime.datetime.now() 30 print(end_time - start_time)
不用协程
import requests import datetime header = { "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36", "Host":"c.oracleinfinity.io", "Accept-Encoding":"gzip, deflate, br", "accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" } def main(): url = "https://www.java.com/zh_CN/" for i in range(5): page = requests.get(url,headers=header).content start_time = datetime.datetime.now() print(start_time) main() end_time = datetime.datetime.now() print(end_time - start_time)
对协程的理解:
例如:小明是一个客服,现在有5个用户同时像他咨询问题。(可以抽象为5个任务)
普通的处理方式是:
1、先完全解决用户1的疑问。(完成任务1)
2、直到用户1回复说没疑问了,再去解决用户2的疑问(完成任务2)
。。。。重复这个过程,直到解决完5个用户的疑问。
协程的处理方式是:
1、回复用户1 。
2、等待用户1回复的过程中,去回复用户2
3、等待用户2回复的过程中,去回复用户3.
4、用户1回复了,继续回复用户1
.......重复这个过程,直到解答完5个用户的疑问。
总之,
1、普通的处理方式就是5个任务依次执行,直到执行完成所有任务。
2、而协程的处理方式是。
(1)任务遇到阻塞(需要等待)的地方时,调度器会去执行其他任务
(2)当需要等待的部分处理完成后,会告诉调度器,我执行完了。然后调度器会继续执行这个任务后续的部分。
(3)重复(1)、(2)过程,直到所有任务处理完毕。