網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
Python?async+request與async+aiohttp實(shí)現(xiàn)異步網(wǎng)絡(luò)請(qǐng)求探索_python
作者:Light2077 ? 更新時(shí)間: 2022-12-01 編程語(yǔ)言前言
在學(xué)習(xí)協(xié)程的時(shí)候,會(huì)有一個(gè)疑問,使用協(xié)程語(yǔ)法進(jìn)行異步請(qǐng)求時(shí),比如async + requests
,會(huì)有用嗎?
其實(shí)細(xì)想一下就知道,由于requests庫(kù)是用同步的方式寫的,因此async + requests
是肯定沒用的。
但是本著實(shí)踐出真知的思想,順便復(fù)習(xí)鞏固一下多線程、async、aiohttp的寫法,還是手動(dòng)來(lái)驗(yàn)證一下。
為了規(guī)避網(wǎng)絡(luò)波動(dòng)等影響,在本地用Flask搭建一個(gè)簡(jiǎn)易的服務(wù)器用于測(cè)試。
先放結(jié)論:
-
threading + requests
能夠并發(fā)請(qǐng)求 -
async + requests
不能并發(fā)請(qǐng)求 -
async + aiohttp
能并發(fā)請(qǐng)求
因此在進(jìn)行爬蟲的時(shí)候,要想加快效率,要么使用threading + requests
,要么就使用async + aiohttp
初始環(huán)境準(zhǔn)備
安裝測(cè)試所需要的庫(kù)
pip install flask
pip install requets
pip install aiohttp
在任意路徑創(chuàng)建一個(gè)文件夾(文件夾名隨意),例如./async_test
在該文件夾下創(chuàng)建一個(gè)空的py文件app.py
用于后續(xù)搭建測(cè)試用后端。
再創(chuàng)建3個(gè)py文件分別對(duì)應(yīng)3個(gè)實(shí)驗(yàn),創(chuàng)建完畢后文件目錄結(jié)構(gòu)如下(此時(shí)的py文件都是空的)
|- async_test
? |- app.py
? |- 1_threading_requests.py
? |- 2_async_requests.py
? |- 3_async_aiohttp.py
搭建測(cè)試用的后端
讓每次請(qǐng)求的時(shí)候先沉睡2秒,再返回結(jié)果,以此來(lái)模擬網(wǎng)絡(luò)延遲。
在app.py
文件中添加如下代碼
## app.py ## from flask import Flask import time app = Flask(__name__) @app.route("/") def index(): time.sleep(2) return "Hello World!" if __name__ == '__main__': app.run()
在./async_test
目錄下運(yùn)行
python app.py
?* Serving Flask app "app" (lazy loading)
?* Environment: production
? ?WARNING: This is a development server. Do not use it in a production deployment.
? ?Use a production WSGI server instead.
?* Debug mode: off
?* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
訪問 http://127.0.0.1:5000/ 延遲2秒后會(huì)看到Hello World!
完成這一步就搭建好了測(cè)試用后端
1.threading requests
在1_threading_requests.py
文件中添加如下代碼
## 1_threading_requests.py ## import time import threading import requests def get(i): print(time.strftime('%X'), 'start', i) resp = requests.get('http://127.0.0.1:5000/') print(time.strftime('%X'), 'end', i) start = time.perf_counter() for i in range(4): threading.Thread(target=get, args=(i,)).start() print(f'total {time.perf_counter() - start:.2f}s ')
在./async_test
目錄下運(yùn)行
python 1_threading_requests.py
09:23:19 start 0
09:23:19 start 1
09:23:19 start 2
09:23:19 start 3
09:23:21 end 2
09:23:21 end 0
09:23:21 end 3
09:23:21 end 1
發(fā)現(xiàn)使用多線程的寫法是能夠并發(fā)請(qǐng)求的。
2.async requests
在2_async_requests.py
文件中添加如下代碼
## 2_async_requests.py ## import time import asyncio import requests async def get(i): print(time.strftime('%X'), 'start', i) resp = requests.get('http://127.0.0.1:5000/') print(time.strftime('%X'), 'end', i) async def main(): for i in range(4): asyncio.create_task(get(i)) asyncio.run(main())
在./async_test
目錄下運(yùn)行
python 2_async_requests.py
09:27:11 start 0
09:27:13 end 0
09:27:13 start 1
09:27:15 end 1
09:27:15 start 2
09:27:17 end 2
09:27:17 start 3
09:27:19 end 3
發(fā)現(xiàn)async+requests
的寫法,代碼是順序執(zhí)行的,異步并沒有起到效果
于是將get(i)
函數(shù)用aiohttp重寫
3.async aiohttp
在3_async_aiohttp.py
文件中添加如下代碼
## 3_async_aiohttp.py ## import time import asyncio import aiohttp import requests async def get(i): print(time.strftime('%X'), 'start', i) async with aiohttp.ClientSession() as session: async with session.get('http://127.0.0.1:5000/') as response: html = await response.text() print(time.strftime('%X'), 'end', i) async def main(): tasks = [asyncio.create_task(get(i)) for i in range(4)] await asyncio.gather(*tasks) asyncio.run(main())
在./async_test
目錄下運(yùn)行
python 3_async_aiohttp.py
09:37:43 start 0
09:37:43 start 1
09:37:43 start 2
09:37:43 start 3
09:37:45 end 0
09:37:45 end 2
09:37:45 end 3
09:37:45 end 1
發(fā)現(xiàn)代碼成功異步執(zhí)行了,總耗時(shí)只有兩秒
說(shuō)明python的協(xié)程語(yǔ)法需要配合異步python庫(kù)才會(huì)生效。
原文鏈接:https://blog.csdn.net/Light2077/article/details/127440915
相關(guān)推薦
- 2022-08-03 GoFrame?glist?基礎(chǔ)使用和自定義遍歷_Golang
- 2022-06-22 Git中tag標(biāo)簽的使用教程_其它綜合
- 2022-10-03 React中路由參數(shù)如何改變頁(yè)面不刷新數(shù)據(jù)的情況_React
- 2022-02-02 【layui】【laydate】設(shè)置可以選擇相同的年份范圍
- 2022-09-29 C++Vector容器常用函數(shù)接口詳解_C 語(yǔ)言
- 2022-04-18 啟動(dòng)項(xiàng)目: getaddrinfo ENOTFOUND localhost
- 2022-04-20 教你python?中如何取出colomap部分的顏色范圍_python
- 2023-01-14 Go編程庫(kù)Sync.Pool用法示例詳解_Golang
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支