Футуры


Объекты футуры используются для соединения низкоуровневого кода, основанного на обратном вызове, с высокоуровневым async/await кодом.

Функции футуры

asyncio.isfuture(obj)

Возвращает True, если obj является одним из:

  • Экземпляром asyncio.Future,
  • Экземпляром asyncio.Task,
  • Футуроподобным объектом с атрибутом _asyncio_future_blocking.

Добавлено в версии 3.5.

asyncio.ensure_future(obj, *, loop=None)

Возвращает:

  • Аргумент obj как есть, если objFuture, Task или объект, подобный футуре (для проверки используется isfuture())
  • Объект Task, оборачивающий obj, если obj — корутина (для проверки используется iscoroutine()); в этом случае корутина будет запланирована ensure_future().
  • Объект Task, который будет ожидать на obj, если obj является ожидаемым (для проверки используется inspect.isawaitable())

Если obj не соответствует ни одному из вышеперечисленных, возникает TypeError.

Важно

См. также функцию create_task(), которая является предпочтительным способом создания новых задач.

Изменено в версии 3.5.1: Функция принимает любой ожидаемый объект.

asyncio.wrap_future(future, *, loop=None)

Обернуть объект concurrent.futures.Future в объект asyncio.Future.

Объект футуры

class asyncio.Future(*, loop=None)

Футура представляет собой конечный результат асинхронной операции. Не потокобезопасный.

Футура — это ожидаемый объект. Корутины могут ожидать на объектах футуры до тех пор, пока у них не будет установлен результат или исключение, или пока они не будут отменены.

Обычно футуры используются для включения низкоуровневого кода на основе обратного вызова (например, в протоколах, реализованных с использованием asyncio транспортов) для взаимодействия с высокоуровневым async/await кодом.

Практическое правило — никогда не раскрывать объекты футуры в API- интерфейсах, ориентированных на пользователя, и рекомендуемый способ создания объекта футуры — это вызвать loop.create_future(). Таким образом, альтернативные реализации событийного цикла могут внедрять свои собственные оптимизированные реализации объекта футуры.

Изменено в версии 3.7: Добавлена поддержка модуля contextvars.

result()

Возвращает результат футуры.

Если футура — выполнена и у неё есть результат, установленный методом set_result(), возвращается значение результата.

Если футура выполнена и у неё есть исключение, установленное методом set_exception(), этот метод вызывает исключение.

Если футура была отменена, этот метод вызывает исключение CancelledError.

Если результат футуры ещё не доступна, этот метод вызывает исключение InvalidStateError.

set_result(result)

Отметить футуру как выполнена и установить её результат.

Вызывает ошибку InvalidStateError, если футура уже выполнена.

set_exception(exception)

Отметить футуру как выполнена и установить исключение.

Вызывает ошибку InvalidStateError, если футура уже выполнена.

done()

Возвращает True, если футура выполнена.

Футура — выполнена, если она была отменена или если у неё результат или исключение, установленное с вызовами set_result() или set_exception().

cancelled()

Возвращает True, если футура была отменена.

Этот метод обычно используется, чтобы проверить, не является ли футура отменённой перед установкой для неё результата или исключения:

if not fut.cancelled():
    fut.set_result(42)
add_done_callback(callback, *, context=None)

Добавить обратный вызов, который будет запускаться, когда футура будет выполнена.

callback вызывается с объектом футуры в качестве единственного аргумента.

Если футура уже выполнена при вызове этого метода, обратный вызов запланирован с loop.call_soon().

Необязательный аргумент context, содержащий только ключевой аргумент, позволяет указать пользовательский contextvars.Context для callback, в котором будет работать. Используется текущий контекст, когда context не указан.

functools.partial() может использоваться для передачи параметров функции обратного вызова, например:

# Вызов 'print("Future:", fut)' когда "fut" выполнен.
fut.add_done_callback(
    functools.partial(print, "Future:"))

Изменено в версии 3.7: Добавлен параметр context, содержащий только ключевой аргумент. См. PEP 567 для получения более подробной информации.

remove_done_callback(callback)

Удалить callback из списка обратных вызовов.

Возвращает количество удаленных обратных вызовов, которое обычно равно 1, если обратный вызов не был добавлен более одного раза.

cancel()

Отменить футуру и запланировать обратные вызовы.

Если футура уже выполнена или отменена, возвращает False. В противном случае изменит состояние футуры на отменена, запланирует обратные вызовы и возвращает True.

exception()

Возвращает исключение, которое было установлено для этой футуры.

Исключение (или None, если исключение не было установлено) возвращается, только если футура выполнена.

Если футура был отменена, этот метод вызывает исключение CancelledError.

Если футура ещё не выполнена, этот метод вызывает исключение InvalidStateError.

get_loop()

Возвращает событийный цикл, к которому привязан объект футуры.

Добавлено в версии 3.7.

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

async def set_after(fut, delay, value):
    # Спать *delay* секунд.
    await asyncio.sleep(delay)

    # Установить *value* как результат *fut* Футуры.
    fut.set_result(value)

async def main():
    # Получить текущий событийный цикл.
    loop = asyncio.get_running_loop()

    # Создание объекта футуры.
    fut = loop.create_future()

    # Запуск "set_after()" корутину в параллельной задаче.
    # Мы используем низкоуровневое "loop.create_task()" API потому что
    # у нас уже есть ссылка на событийный цикл под рукой.
    # В противном случае мы могли бы просто использовать "asyncio.create_task()".
    loop.create_task(
        set_after(fut, 1, '... world'))

    print('hello ...')

    # Подождать, пока *fut* не получит результат (1 секунда) и распечатать его.
    print(await fut)

asyncio.run(main())

Важно

Объект футуры был разработан для имитации concurrent.futures.Future. Основные отличия: