Рубрики
Без рубрики

Асинхронное получение результатов

Автор оригинала: Doug Hellmann.

Future представляет результат еще не завершенной работы. Цикл событий может отслеживать состояние объекта Future , чтобы указать, что это сделано, позволяя одной части приложения ждать, пока другая часть завершит некоторую работу.

В ожидании будущего

Future действует как сопрограмма, поэтому любые методы, полезные для ожидания сопрограммы, также могут использоваться для ожидания, пока будущее не будет помечено как выполненное. В этом примере будущее передается в метод run_until_complete () цикла событий.

asyncio_future_event_loop.py

import asyncio


def mark_done(future, result):
    print('setting future result to {!r}'.format(result))
    future.set_result(result)


event_loop  asyncio.get_event_loop()
try:
    all_done  asyncio.Future()

    print('scheduling mark_done')
    event_loop.call_soon(mark_done, all_done, 'the result')

    print('entering event loop')
    result  event_loop.run_until_complete(all_done)
    print('returned result: {!r}'.format(result))
finally:
    print('closing event loop')
    event_loop.close()

print('future result: {!r}'.format(all_done.result()))

Состояние Future изменяется на done при вызове set_result () , а экземпляр Future сохраняет результат, переданный методу, для последующего извлечения .

$ python3 asyncio_future_event_loop.py

scheduling mark_done
entering event loop
setting future result to 'the result'
returned result: 'the result'
closing event loop
future result: 'the result'

Future также можно использовать с ключевым словом await , как в этом примере.

asyncio_future_await.py

import asyncio


def mark_done(future, result):
    print('setting future result to {!r}'.format(result))
    future.set_result(result)


async def main(loop):
    all_done  asyncio.Future()

    print('scheduling mark_done')
    loop.call_soon(mark_done, all_done, 'the result')

    result  await all_done
    print('returned result: {!r}'.format(result))


event_loop  asyncio.get_event_loop()
try:
    event_loop.run_until_complete(main(event_loop))
finally:
    event_loop.close()

Результат Future возвращается await , поэтому часто можно иметь один и тот же код, работающий с обычной сопрограммой и экземпляром Future .

$ python3 asyncio_future_await.py

scheduling mark_done
setting future result to 'the result'
returned result: 'the result'

Будущие обратные вызовы

В дополнение к работе как сопрограмма, Future может вызывать обратные вызовы по завершении. Обратные вызовы вызываются в порядке их регистрации.

asyncio_future_callback.py

import asyncio
import functools


def callback(future, n):
    print('{}: future done: {}'.format(n, future.result()))


async def register_callbacks(all_done):
    print('registering callbacks on future')
    all_done.add_done_callback(functools.partial(callback, n1))
    all_done.add_done_callback(functools.partial(callback, n2))


async def main(all_done):
    await register_callbacks(all_done)
    print('setting result of future')
    all_done.set_result('the result')


event_loop  asyncio.get_event_loop()
try:
    all_done  asyncio.Future()
    event_loop.run_until_complete(main(all_done))
finally:
    event_loop.close()

Обратный вызов должен ожидать один аргумент, экземпляр Future . Чтобы передать дополнительные аргументы обратным вызовам, используйте functools.partial () для создания оболочки.

$ python3 asyncio_future_callback.py

registering callbacks on future
setting result of future
1: future done: the result
2: future done: the result