代码之家  ›  专栏  ›  技术社区  ›  Phil

python aiohtp:在满足条件时取消异步执行

  •  1
  • Phil  · 技术社区  · 5 年前

    我为一个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 回复  |  直到 5 年前
        1
  •  2
  •   user4815162342    5 年前

    我想知道这是不是在AIOHTTP做这件事的正确方法

    您的代码相当惯用。在顶层,你可以忽略 asyncio.ensure_future 简单的呼叫 asyncio.run(run(possible_answers)) .

    当条件(状态代码)满足时,如何取消处理?

    您可以使用事件或将来的对象并等待它,而不是使用 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()