Назовите asyncio Future в поле зрения - PullRequest
2 голосов
/ 03 июля 2019

Я пытаюсь добиться прогресса в моем asyncIO Futures. По какой-то причине я не могу получить обновления значений внутри какой-либо другой области.

Например:

import concurrent.futures
import time
import asyncio
import random

def get_progress(futures):
    return sum([f.done() for f in futures])

def long_task(t):
    time.sleep(1.5)
    return t

loop = asyncio.get_event_loop()
executor = concurrent.futures.ProcessPoolExecutor(max_workers=4)
inputs = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
futures_ = [loop.run_in_executor(executor, long_task, i) for i in inputs]

for i in range(5):
    time.sleep(1)
    print(get_progress(futures_))

Печатает только 0. Однако, если я запускаю это в терминале и вызываю get_progress(futures_), он печатает 7, как и ожидалось.

Я что-то здесь упускаю?

1 Ответ

1 голос
/ 04 июля 2019

Asyncio futures , возвращаемое run_in_executor, предназначено для запуска в цикле событий asyncio и отличается от одновременных . Правильный асинхронный код будет выглядеть так:

async def track_progress():
    for i in range(5):
        await asyncio.sleep(1)
        print(get_progress(futures_))

loop.run_until_complete(track_progress())

Печатает 0 4 4 7 7.

Обратите внимание, что вам не нужно asyncio и run_in_executor, если вы просто хотите запускать вещи в потоках - concurrent.futures вполне способен справиться с этим самостоятельно. Например:

executor = concurrent.futures.ProcessPoolExecutor(max_workers=4)
inputs = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
futures_ = [executor.submit(long_task, i) for i in inputs]

Поскольку executor.submit реальных параллельных фьючерсов, futures_ также содержит их. С этой модификацией ваш оригинальный цикл for, который отслеживает их прогресс, будет работать нормально, а также печатать 0 4 4 7 7.

...