Почему ожидание asyncio.Future в Python 3.7 сообщает об исключении вместо ожидания установки значения / исключения? - PullRequest
2 голосов
/ 10 октября 2019

Когда я запускаю следующий код Python:

import asyncio
import logging
logging.basicConfig(level=logging.DEBUG)

async def read_future(fut):
    print(await fut)

async def write_future(fut):
    fut.set_result('My Value')

async def main():
    loop = asyncio.get_running_loop()
    fut = loop.create_future()
    asyncio.gather(read_future(fut), write_future(fut))

asyncio.run(main(), debug=True)

Вместо read_future в ожидании установки результата fut программа вылетает со следующей ошибкой:

DEBUG:asyncio:Using selector: KqueueSelector
ERROR:asyncio:_GatheringFuture exception was never retrieved
future: <_GatheringFuture finished exception=CancelledError() created at /Users/<user>/.pyenv/versions/3.7.4/lib/python3.7/asyncio/tasks.py:642>
source_traceback: Object created at (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/<user>/.pyenv/versions/3.7.4/lib/python3.7/asyncio/runners.py", line 43, in run
    return loop.run_until_complete(main)
  File "/Users/<user>/.pyenv/versions/3.7.4/lib/python3.7/asyncio/base_events.py", line 566, in run_until_complete
    self.run_forever()
  File "/Users/<user>/.pyenv/versions/3.7.4/lib/python3.7/asyncio/base_events.py", line 534, in run_forever
    self._run_once()
  File "/Users/<user>/.pyenv/versions/3.7.4/lib/python3.7/asyncio/base_events.py", line 1763, in _run_once
    handle._run()
  File "/Users/<user>/.pyenv/versions/3.7.4/lib/python3.7/asyncio/events.py", line 88, in _run
    self._context.run(self._callback, *self._args)
  File "<stdin>", line 4, in main
  File "/Users/<user>/.pyenv/versions/3.7.4/lib/python3.7/asyncio/tasks.py", line 766, in gather
    outer = _GatheringFuture(children, loop=loop)
  File "/Users/<user>/.pyenv/versions/3.7.4/lib/python3.7/asyncio/tasks.py", line 642, in __init__
    super().__init__(loop=loop)
concurrent.futures._base.CancelledError
DEBUG:asyncio:Close <_UnixSelectorEventLoop running=False closed=False debug=True>

Что я делаю не так в этом коде? Я хочу иметь возможность ждать Future fut и продолжать после того, как для Future установлено значение / исключение.

Ответы [ 2 ]

1 голос
/ 10 октября 2019

Ваша проблема в том, что asyncio.gather само по себе является асинхронным (возвращает ожидаемое);не await его, вы никогда не возвращали управление в цикл обработки событий и не сохраняли ожидаемое, поэтому оно было немедленно очищено, неявно отменено и, соответственно, все ожидаемые элементы, которыми оно управляло.

Чтобы исправить, просто убедитесь, что вы await результаты gather:

await asyncio.gather(read_future(fut), write_future(fut))

Попробуйте онлайн!

0 голосов
/ 10 октября 2019

С https://docs.python.org/3/library/asyncio-future.html#asyncio.Future.result:

result()

Возвращает результат будущего.

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

Если Future done и имеет исключение, установленное методом set_exception(), этот метод вызываетисключение.

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

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

(жирный шрифт добавлен.)

Я не уверен, почему Future отменяется, но это, кажется, причина проблемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...