Как обернуть пользовательское будущее для использования с 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.

Другие вопросы по тегам