Как обернуть пользовательское будущее для использования с Asyncio в Python?
Есть много библиотек, которые используют свои собственные версии Future. kafka и s3transfer - всего лишь два примера: все их пользовательские классы будущего object
как суперкласс.
Не удивительно, что вы не можете напрямую позвонить asyncio.wrap_future()
на таких объектах и не может использовать await
с ними.
Как правильно обернуть такие фьючерсы для использования с Asyncio?
1 ответ
Если будущий класс поддерживает стандартные будущие функции, такие как готовые обратные вызовы и result
метод, просто используйте что-то вроде этого:
def wrap_future(f):
loop = asyncio.get_event_loop()
aio_future = loop.create_future()
def on_done(*_):
try:
result = f.result()
except Exception as e:
loop.call_soon_threadsafe(aio_future.set_exception, e)
else:
loop.call_soon_threadsafe(aio_future.set_result, result)
f.add_done_callback(on_done)
return aio_future
Рассмотрим этот код как шаблон, который вы можете настроить в соответствии со спецификой будущего, с которым вы имеете дело.
Предполагаемое использование - вызвать его из потока, который запускает цикл событий asyncio:
value = await wrap_future(some_foreign_future)
Если вы вызываете его из другого потока, обязательно передайте loop
явно, потому что asyncio.get_event_loop
потерпит неудачу при вызове из потока, не зарегистрированного в asyncio.