前言
真就一年发一篇。这一年发生了好多事,把我打得手忙脚乱,短短一年,物是人非。
昨天写awd相关脚本,想着来点狠的,加速混淆流量发包,试试异步。正好看到github上有相关源码,requests+asyncio。
想着requests是阻塞的怎么能用异步呢?折腾了好久,看着12345顺序发包,这他娘不就是同步发送吗!!
得,都花那么长时间了,来都来了。又开始研究异步原理,尝试httpx+asyncio。折腾好久,失败了。
翻文档视频教程到11点,最后发现,
async with httpx.AsyncClient() as client:
pass
httpx.AsyncClient
后面的小括号没加,try捕捉到的报错又被我pass了
无语,姑且把中间做的笔记记一下吧。
笔记
await 后面只能跟:协程对象,task对象,future对象
await意义:等待一个函数结束,在等待的过程中切换到其他函数执行以免浪费时间。以此实现并发。
python>=3.7之后,建议用asyncio.create_task()
创建task对象
注释事项
直接
await task
不会对并发有帮助错误用法:
async def s(): await asyncio.create_task(func1()) await asyncio.create_task(func2())
正确用法:
async def s(): task1 = asyncio.create_task(func1()) task2 = asyncio.create_task(func2()) await task1 await task2
启动
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Python3.7之后新增接口
asyncio.run(asyncio.wait(main()))
两者等价
实用范例
- 范例1 在协程函数内部创建tasks并组合
async def main():
tasks=[asyncio.create_task(func1()),asyncio.create_task(func2())]
done,pending = await asyncio.wait(tasks)
asyncio.run(main())
- 范例2 在外面把协程函数组合成tasks
async def func():
await asyncio.sleep(2)
tasks=[func(),func()]
asyncio.run(asyncio.wait(tasks))
asyncia+非异步函数搭配
requests默认不支持异步,但可以通过线程池配合实现。但耗费资源较多
async def _request(url):
loop = asyncio.get_event_loop()
future = loop.run_in_executor(None, requests.get, url)
res = await future
tasks = [_request(url) for url in url_list]
asyncio.run(asyncio.wait(tasks))
uvloop,性能提升!
用uvloop代替asyncio默认的事件循环以提升2倍以上性能。
import asyncio
import uvloop
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
# 后续代码与asyncio代码一致,内部事件循环会自动转化为uvloop
python模块uvloop暂不支持windows和python3.9