异步asyncio学习笔记


前言

真就一年发一篇。这一年发生了好多事,把我打得手忙脚乱,短短一年,物是人非。

昨天写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


文章作者: 巡璃
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 巡璃 !
评论
  目录