Python aiohttp:在满足条件的情况下取消异步执行

时间:2019-01-22 07:39:55

标签: python python-3.x python-asyncio aiohttp

我已经为CTF游戏编写了一个异步暴力脚本,如下所示:

async def bound_fetch(sem, session, answer):
    #  generating url, headers and json ...
    async with sem, session.post(url=url, json=json, headers=headers) as response:
        if response.status == 200:
            print('Right answer found: %s' % json['answer'])


async def run(words):
    tasks = []
    sem = asyncio.Semaphore(3)
    async with aiohttp.ClientSession() as session:
        for word in words:
            task = asyncio.create_task(bound_fetch(sem=sem, session=session, answer=''.join(word)))
            tasks.append(task)
        print("Generated %d possible answers. Checking %s" % (len(tasks), base_url))
        await asyncio.gather(*tasks)


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    future = asyncio.ensure_future(run(possible_answers))
    loop.run_until_complete(future)

我的参考资料是本教程:https://pawelmhm.github.io/asyncio/python/aiohttp/2016/04/22/asyncio-aiohttp.html

我想知道这是否是在aiohttp中执行此操作的正确方法,还是使事情变得过于复杂(因为我不需要处理所有响应,只需知道哪个响应的状态为200)即可?满足条件(状态码)时如何取消处理?

1 个答案:

答案 0 :(得分:2)

  

我想知道这是否是在aiohttp中正确的方法

您的代码是惯用的。在顶层,您可以省略asyncio.ensure_future并只需调用asyncio.run(run(possible_answers))

  

在满足条件(状态码)的情况下如何取消处理?

您可以使用事件或将来的对象并等待它,而不要使用gather。如您所知,{em}不需要gather来运行协程(它们在create_task的安排下立即运行),其明确的目的是等到所有协程完成。基于Event的同步如下所示:

async def bound_fetch(sem, session, answer, done):
    #  generating url, headers and json ...
    async with sem, session.post(url=url, json=json, headers=headers) as response:
        if response.status == 200:
            done.set()
            done.run_answer = json['answer']

async def run(words):
    sem = asyncio.Semaphore(3)
    done = asyncio.Event()
    async with aiohttp.ClientSession() as session:
        tasks = []
        for word in words:
            tasks.append(asyncio.create_task(bound_fetch(
                sem=sem, session=session, answer=''.join(word), done=done)))
        print("Generated %d possible answers. Checking %s" % (len(words), base_url))
        await done.wait()
        print('Right answer found: %s' % done.run_answer)
        for t in tasks:
            t.cancel()