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。当然这个时间对比可能不是非常准确,因为请求过程还受其他因素影响,不过应该能大致说明问题。

代码语言:javascript
复制
 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)

不用协程

代码语言:javascript
复制
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)过程,直到所有任务处理完毕。