Python aiohttp: отменить асинхронное выполнение при соблюдении условия - PullRequest
0 голосов
/ 22 января 2019

Я написал сценарий асинхронного перебора для игры 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 голосов
/ 22 января 2019

Мне было интересно, если это правильный способ сделать это в aiohttp

Ваш код достаточно идиоматичен. На верхнем уровне вы можете опустить asyncio.ensure_future и просто позвонить asyncio.run(run(possible_answers)).

Как отменить обработку при выполнении условия (кода состояния)?

Вы можете использовать событие или будущий объект и ждать его вместо использования gather. Как вы, вероятно, знаете, 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()
...