python asyncio tcp转发_aiohttp + asyncio 异步网络请求基本操作
作者:matrix
被圍觀: 1,949 次
發布時間:2019-11-26
無評論 ?
💡NOTICE:這是一個創建于 379 天前的主題,其中的信息可能已經有所發展或是發生改變。最近修改:2020-08
asyncio異步操作需要關鍵字async,await。
async用來聲明方法函數,await用來聲明耗時操作。
但是await關鍵字后面要求為awaitable對象 且只能在async方法內部使用,不能在外部入口中使用。asyncio的語法其實是系統內部實現了yield from協程。
aiohttp用來代替requests的請求庫,且支持異步操作。
主要優點體現在并發請求多個耗時任務時,自動安排耗時時的操作,避免cpu等待一個一個請求。
單個請求操作
import aiohttp
import asyncio
#get 請求
async def get():
async with aiohttp.request('GET','https://api.github.com/users/Ho',params={'arg1':123}) as response:
# response.request_info # 請求信息
return await response.json()
rel = asyncio.run(get())
# 或者使用下面方式 手動關閉異步事件循環
# loop = asyncio.get_event_loop()
# rel = loop.run_until_complete(get())
# loop.close()
print(rel)
多個并發請求操作
主要區別在于異步任務的添加操作,運行。
請求測試url:
http://link/await/1 # delay 1sec
http://link/await/2 # delay 2sec
...
請求測試:
import aiohttp
import asyncio
#get 請求
async def get():
async with aiohttp.request('GET','http://link/await/1') as response:
return await response.text()
# 所有請求任務
async def all_req():
#async with asyncio.Semaphore(5): 設置并發的連接數
# https://docs.python.org/zh-cn/3/library/asyncio-sync.html#asyncio.Semaphore
task = []
#添加請求任務
for i in range(5):
task.append(asyncio.create_task(get()))
#create_task 方法等同于 ensure_future()方法
#手冊建議首選 create_task方法
# https://docs.python.org/zh-cn/3/library/asyncio-future.html?highlight=ensure_future#asyncio.ensure_future
return await asyncio.gather(*task)#傳入參數 tuple類型 作為位置參數
# 等同于 asyncio.gather(get(),get())
# gather()方法用于收集所有任務完成的返回值,如果換成wait()方法會返回任務tuple對象,(done,pending)
rel = asyncio.run(all_req())
print(rel)
# 總共5個請求任務返回:
# 總耗時1秒多,相比同步的5秒+好N多。
"""
['sleep 1 second is done', 'sleep 1 second is done', 'sleep 1 second is done', 'sleep 1 second is done', 'sleep 1 second is done']
[Done] exited with code=0 in 1.955 seconds
"""
tell why??
測試發現Semaphore方法設置的請求并發數量跟本不起作用,nginx的access.log以及Proxifier看到的一次性請求量都不是代碼中設置的數量。
使用uvloop優化異步操作
uvloop用于提升協程的速度。
uvloop使用很簡單,直接設置異步策略就好了。
import asyncio
import uvloop
#聲明使用 uvloop 事件循環
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
測試遇到很多報錯,基本上都是await和async使用的問題。
異步請求的分塊chunk并發控制
自行chunk操作
自己按照所有任務的list列表進行chunk切割,然后分塊進行請求,每塊中固定chunk數量的任務?;究梢詫崿F想要的并發限制操作
async def _bulk_task(num,current_page = 1):
"""批量創建異步任務
"""
task = []
for i in range(num):# 每次10個連接并發進行請求
task.append(asyncio.create_task(get(current_page)))
current_page += 1
return await asyncio.gather(*task)
# 主要進行chunk操作的函數
def run_task(total,chunk,offset_start_page = 1):
"""運行分塊處理的批量任務
Arguments:
total int 總請求數
chunk int 每次并發請求數
offset_start_page int 初始分塊開始的頁數(偏移頁數),正常默認為1
Yields:
返回收集的異步任務運行結果
"""
length = math.ceil(total/chunk)
for i in range(length):
start_page = i * chunk + offset_start_page # 當前分塊開始的頁數
haldle_num = chunk# 當前需要并發處理的數量
#處理結尾的塊
if i == length - 1:
# print(':::',chunk,start_page + chunk - offset_start_page)
haldle_num = min(chunk,total + offset_start_page - start_page)
# print('當前分塊下標:{},當前分塊需要處理的總數:{},當前分塊開始頁數:{}'.format(i,haldle_num,start_page))
rel = asyncio.run(_bulk_task(haldle_num,start_page))
yield rel
rel = run_task(123,10)# 123總任務 每10條并發請求
for i in rel:
print(i)
TODO
參考:
https://hubertroy.gitbooks.io/aiohttp-chinese-documentation/content/aiohttp%E6%96%87%E6%A1%A3/ClientUsage.html#%E6%84%89%E5%BF%AB%E5%9C%B0%E7%BB%93%E6%9D%9F
https://docs.Python.org/zh-cn/3/library/asyncio-eventloop.html#asyncio.get_running_loop
https://segmentfault.com/q/1010000008663962
http://www.ruanyifeng.com/blog/2019/11/python-asyncio.html
https://blog.csdn.net/qq_37144341/article/details/89471603
https://www.jianshu.com/p/8f65e50f39b4
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的python asyncio tcp转发_aiohttp + asyncio 异步网络请求基本操作的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 空格的ascii码_美国信息交换标准代码
- 下一篇: 防骗小技巧:五招识破虚假购物网站