Python - Как заставить задачи выполняться асинхронно, используя asyncio - PullRequest
0 голосов
/ 01 июня 2018

Я пытался запустить 2 задачи одновременно для одного клиента из списка, но он не работал должным образом - задачи по-прежнему выполнялись синхронно (см. Output).Можете ли вы помочь мне понять, что не так с моим кодом?Спасибо.

Код

#!/usr/bin/env python3

import asyncio


async def do_b(client):
    print('{}: doing b...'.format(client))
    await asyncio.sleep(1)
    print('{}: b is done!'.format(client))


async def do_a(client):
    print('{}: doing a...'.format(client))
    await asyncio.sleep(1)
    print('{}: a is done!'.format(client))


async def loop_a():
    clients = ['CLIENT-1', 'CLIENT-2', 'CLIENT-3', 'CLIENT-4', 'CLIENT-5']

    for client in clients:
        task1 = asyncio.ensure_future(do_a(client))
        task2 = asyncio.ensure_future(do_b(client))

        await asyncio.gather(task1, task2)


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(loop_a())
    loop.close()

Вывод

CLIENT-1: doing a...
CLIENT-1: doing b...
CLIENT-1: a is done!
CLIENT-1: b is done!
CLIENT-2: doing a...
CLIENT-2: doing b...
CLIENT-2: a is done!
CLIENT-2: b is done!
CLIENT-3: doing a...
CLIENT-3: doing b...
CLIENT-3: a is done!
CLIENT-3: b is done!
CLIENT-4: doing a...
CLIENT-4: doing b...
CLIENT-4: a is done!
CLIENT-4: b is done!
CLIENT-5: doing a...
CLIENT-5: doing b...
CLIENT-5: a is done!
CLIENT-5: b is done!

РЕДАКТИРОВАТЬ:

Еще один вопрос.Как сделать так, чтобы он выполнялся так, чтобы не следовать их порядку в списке?Потому что в настоящее время CLIENT-1 блокируется CLIENT-2, так же, как и другие клиенты, и я пытался избежать этого.Возможно ли это?

CLIENT-1: doing a...
CLIENT-2: doing a...
CLIENT-1: doing b...
CLIENT-3: doing a...
CLIENT-1: a is done!
CLIENT-1: b is done!
CLIENT-2: a is done!
CLIENT-3: a is done!
CLIENT-2: doing b...
CLIENT-2: b is done!
CLIENT-3: doing b...
CLIENT-3: b is done!

Ответы [ 2 ]

0 голосов
/ 01 июня 2018

a и b работают одновременно, и выход показывает, что.Клиенты 1, 2, 3, 4 и 5 работают последовательно, потому что между ними есть await asyncio.gather.

Вы можете объединить все задачи в один список, чтобы они выполнялись одновременно:

async def loop_a():
    clients = ['CLIENT-1', 'CLIENT-2', 'CLIENT-3', 'CLIENT-4', 'CLIENT-5']

    tasks = []
    for client in clients:
        tasks.append(asyncio.ensure_future(do_a(client)))
        tasks.append(asyncio.ensure_future(do_b(client)))
    await asyncio.gather(*tasks)

Теперь он печатает:

CLIENT-1: doing a...
CLIENT-1: doing b...
CLIENT-2: doing a...
CLIENT-2: doing b...
CLIENT-3: doing a...
CLIENT-3: doing b...
CLIENT-4: doing a...
CLIENT-4: doing b...
CLIENT-5: doing a...
CLIENT-5: doing b...
CLIENT-1: a is done!
CLIENT-2: a is done!
CLIENT-3: b is done!
CLIENT-1: b is done!
CLIENT-3: a is done!
CLIENT-2: b is done!
CLIENT-4: a is done!
CLIENT-5: b is done!
CLIENT-4: b is done!
CLIENT-5: a is done!
0 голосов
/ 01 июня 2018

Во-первых, две задачи не работают синхронно, как видно из того факта, что doing b... продолжает появляться в промежутке между doing a... и a is done!.

Каждая пара задач заканчивается до запуска следующего клиента, но это потому, что вы явно просите, чтобы это произошло.Если вы не хотите await каждой пары, просто ... не await каждой пары.Например:

futs = []
for client in clients:
    futs.append(asyncio.ensure_future(do_a(client)))
    futs.append(asyncio.ensure_future(do_b(client)))
await asyncio.gather(*futs)
...