Создание индикатора прогресса tqdm для asyncio - PullRequest
0 голосов
/ 05 апреля 2020

Я пытаюсь выполнить индикатор прогресса tqdm с собранными асинхронными заданиями.

Хотите, чтобы индикатор выполнения постепенно обновлялся по завершении задачи. Попробовал код:

import asyncio
import tqdm
import random

async def factorial(name, number):
    f = 1
    for i in range(2, number+1):
        await asyncio.sleep(random.random())
        f *= i
    print(f"Task {name}: factorial {number} = {f}")

async def tq(flen):
    for _ in tqdm.tqdm(range(flen)):
        await asyncio.sleep(0.1)

async def main():
    # Schedule the three concurrently

    flist = [factorial("A", 2),
        factorial("B", 3),
        factorial("C", 4)]

    await asyncio.gather(*flist, tq(len(flist)))

asyncio.run(main())

... но это просто завершает строку tqdm и затем обрабатывает факториалы.

Есть ли способ заставить индикатор выполнения двигаться после завершения каждой асинхронной задачи

Ответы [ 2 ]

2 голосов
/ 05 апреля 2020

Теперь я не особо знаком с asyncho, хотя я использовал tqdm с некоторым успехом для многопроцессорных систем в python. Следующее изменение в вашем коде, по-видимому, обновляет индикатор выполнения и одновременно печатает результат, которого может быть достаточно для начала работы.

responses = [await f
                 for f in tqdm.tqdm(asyncio.as_completed(flist), total=len(flist))]

Выше следует заменить await asyncio.gather(*flist, tq(len(flist))) в вашем main определение.

Для получения дополнительной информации, вышеприведенное было вдохновлено с индикатор выполнения asyncio aiohttp с tqdm

Чтобы напечатать панель только один раз и обновить ее, я сделал следующий, который обновляет описание индикатора выполнения, чтобы включить ваше сообщение:

import asyncio
import tqdm


async def factorial(name, number):
    f = 1
    for i in range(2, number + 1):
        await asyncio.sleep(1)
        f *= i
    return f"Task {name}: factorial {number} = {f}"

async def tq(flen):
    for _ in tqdm.tqdm(range(flen)):
        await asyncio.sleep(0.1)


async def main():
    # Schedule the three concurrently

    flist = [factorial("A", 2),
             factorial("B", 3),
             factorial("C", 4)]

    pbar = tqdm.tqdm(total=len(flist))
    for f in asyncio.as_completed(flist):
        value = await f
        pbar.set_description(value)
        pbar.update()

if __name__ == '__main__':
    asyncio.run(main())
0 голосов
/ 07 апреля 2020

Внес несколько небольших изменений в код Dragos в формате pbar и использовал tqdm.write(), чтобы получить почти то, что я хочу, следующим образом:

import asyncio
import random

import tqdm


async def factorial(name, number):
    f = 1
    for i in range(2, number + 1):
        await asyncio.sleep(random.random())
        f *= i
    return f"Task {name}: factorial {number} = {f}"

async def tq(flen):
    for _ in tqdm.tqdm(range(flen)):
        await asyncio.sleep(0.1)


async def main():

    flist = [factorial("A", 2),
             factorial("B", 3),
             factorial("C", 4)]

    pbar = tqdm.tqdm(total=len(flist), position=0, ncols=90)
    for f in asyncio.as_completed(flist):
        value = await f
        pbar.set_description(desc=value, refresh=True)
        tqdm.tqdm.write(value)
        pbar.update()

if __name__ == '__main__':
    asyncio.run(main())
...