Содержание страницы
Future¶Futures
Исходный код: Lib/asyncio/futures.py, Lib/asyncio/base_futures.py
Future-объекты используются для связи низкоуровневого кода на основе колбэков с высокоуровневым кодом async/await.
Функции Future¶Future Functions
- asyncio.isfuture(obj)¶
Возвращает
True, если obj – это:экземпляр
asyncio.Future,экземпляр
asyncio.Task,Future-подобный объект с атрибутом
_asyncio_future_blocking.
Новое в версии 3.5.
- asyncio.ensure_future(obj, *, loop=None)¶
Возвращает:
obj как есть, если obj –
Future,Taskили Future-подобный объект (проверка выполняется с помощьюisfuture()).объект
Task, оборачивающий obj, если obj – корутина (проверка выполняется с помощьюiscoroutine()); в этом случае корутина будет запланирована черезensure_future().объект
Task, который будет ожидать obj, если obj является ожидаемым объектом (проверка выполняется с помощьюinspect.isawaitable()).
Если obj не является ни одним из вышеперечисленных, возбуждается
TypeError.Важно
См. также функцию
create_task(), которая является предпочтительным способом создания новых задач.Сохраняйте ссылку на результат этой функции, чтобы избежать исчезновения задачи во время выполнения.
Изменено в версии 3.5.1: Функция принимает любой ожидаемый объект.
Устарело с версии 3.10: Предупреждение об устаревании выводится, если obj не является Future-подобным объектом и loop не указан, и нет работающего цикла событий.
- asyncio.wrap_future(future, *, loop=None)¶
Оборачивает объект
concurrent.futures.Futureв объектasyncio.Future.Устарело с версии 3.10: Предупреждение об устаревании выводится, если future не является Future-подобным объектом и loop не указан, и нет работающего цикла событий.
Объект Future¶Future Object
- class asyncio.Future(*, loop=None)¶
Future представляет собой окончательный результат асинхронной операции. Не потокобезопасен.
Future – это ожидаемый объект. Корутины могут ожидать объекты Future, пока у них не будет установлен результат или исключение, или пока они не будут отменены. Future можно ожидать несколько раз, и результат будет одинаковым.
Обычно Futures используются для того, чтобы низкоуровневый код на основе колбэков (например, в протоколах, реализованных с помощью asyncio транспорты) мог взаимодействовать с высокоуровневым кодом async/await.
Эмпирическое правило: никогда не предоставлять объекты Future в пользовательских API, а рекомендуемый способ создания объекта Future – вызвать
loop.create_future(). Таким образом, альтернативные реализации цикла событий могут внедрять свои собственные оптимизированные реализации объекта Future.Изменено в версии 3.7: Добавлена поддержка модуля
contextvars.Устарело с версии 3.10: Предупреждение об устаревании выводится, если loop не указан и нет работающего цикла событий.
- result()¶
Возвращает результат объекта Future.
Если Future находится в состоянии done и имеет результат, установленный методом
set_result(), возвращается значение результата.Если Future находится в состоянии done и имеет исключение, установленное методом
set_exception(), этот метод возбуждает это исключение.Если Future был отменён, этот метод возбуждает исключение
CancelledError.Если результат Future ещё недоступен, этот метод вызывает исключение
InvalidStateError.
- set_result(result)¶
Помечает Future как done и устанавливает его результат.
Вызывает ошибку
InvalidStateError, если Future уже завершён.
- set_exception(exception)¶
Помечает Future как done и устанавливает исключение.
Вызывает ошибку
InvalidStateError, если Future уже завершён.
- done()¶
Возвращает
True, если Future находится в состоянии done.Future находится в состоянии done, если оно было отменено или если у него есть результат или исключение, установленные вызовами
set_result()илиset_exception().
- cancelled()¶
Возвращает
True, если Future был отменён.Этот метод обычно используется для проверки того, не был ли Future отменён, перед установкой результата или исключения:
if not fut.cancelled(): fut.set_result(42)
- add_done_callback(callback, *, context=None)¶
Добавляет колбэк, который будет выполнен, когда Future перейдёт в состояние done.
Колбэк вызывается с объектом Future в качестве единственного аргумента.
Если Future уже находится в состоянии done на момент вызова этого метода, колбэк планируется с помощью
loop.call_soon().Необязательный аргумент context (только ключевой) позволяет указать пользовательский
contextvars.Contextдля выполнения колбэка. Если context не указан, используется текущий контекст.functools.partial()можно использовать для передачи параметров колбэку, например:# Вызвать 'print("Future:", fut)', когда "fut" будет завершён. fut.add_done_callback( functools.partial(print, "Future:"))
Изменено в версии 3.7: Добавлен параметр context (только ключевой). Подробнее см. PEP 567.
- remove_done_callback(callback)¶
Удаляет колбэк из списка колбэков.
Возвращает количество удалённых колбэков – обычно 1, если только колбэк не был добавлен более одного раза.
- cancel(msg=None)¶
Отменяет Future и планирует выполнение колбэков.
Если Future уже завершён или отменён, вернуть
False. Иначе перевести Future в состояние отменён, запланировать колбэки и вернутьTrue.Изменено в версии 3.9: Добавлен параметр msg.
- exception()¶
Возвращает исключение, которое было установлено для этого Future.
Исключение (или
None, если исключение не было установлено) возвращается только если Future завершён.Если Future был отменён, этот метод возбуждает исключение
CancelledError.Если Future ещё не завершён, этот метод возбуждает исключение
InvalidStateError.
- get_loop()¶
Возвращает цикл событий, к которому привязан объект Future.
Добавлено в версии 3.7.
В этом примере создаётся объект Future, создаётся и планируется асинхронная задача для установки результата Future, и выполняется ожидание, пока Future не получит результат:
async def set_after(fut, delay, value):
# Приостановиться на *delay* секунд.
await asyncio.sleep(delay)
# Установить *value* в качестве результата Future *fut*.
fut.set_result(value)
async def main():
# Получить текущий цикл событий.
loop = asyncio.get_running_loop()
# Создать новый объект Future.
fut = loop.create_future()
# Запустить корутину "set_after()" в параллельной задаче.
# Мы используем низкоуровневый API "loop.create_task()", поскольку
# у нас уже есть ссылка на цикл событий.
# В противном случае можно было бы просто использовать "asyncio.create_task()".
loop.create_task(
set_after(fut, 1, '... world'))
print('hello ...')
# Ожидать, пока у *fut* не появится результат (1 секунда), и вывести его.
print(await fut)
asyncio.run(main())
Важно
Объект Future был спроектирован так, чтобы имитировать
concurrent.futures.Future. Ключевые отличия включают:
в отличие от asyncio Future, экземпляры
concurrent.futures.Futureнельзя ожидать.asyncio.Future.result()иasyncio.Future.exception()не принимают аргумент timeout.asyncio.Future.result()иasyncio.Future.exception()возбуждают исключениеInvalidStateError, когда Future не завершён.Колбэки, зарегистрированные с помощью
asyncio.Future.add_done_callback(), вызываются не сразу. Вместо этого они планируются с помощьюloop.call_soon().asyncio Future несовместим с функциями
concurrent.futures.wait()иconcurrent.futures.as_completed().asyncio.Future.cancel()принимает необязательный аргументmsg, аconcurrent.futures.Future.cancel()– нет.