Запуск асинхронных методов с использованием оператора with в синхронном методе - PullRequest
0 голосов
/ 17 октября 2018

Многие из моих представлений Django нуждаются в ручке.Создание этого дескриптора и операции над ним являются асинхронными.Я также хочу использовать оператор with для автоматического закрытия дескриптора.

Я не уверен, где поставить мост между асинхронным и синхронным кодом.

Что у меня есть

Я реализовал opened() метод, который работает как менеджер контекста :

@contextmanager
async def opened(self):
    handle = await library.open_asynchronnously()
    try:
        yield handle
    finally:
        await library.close_asynchronously(handle)

В представлении Я хочу использовать его следующим образом

def server_detail(request,server):
    with Server.opened(server) as server_handle:
       result = do(asynchronous_call(server_handle))
    return result

Я также использую метод do() для запуска асинхронного кода внутри синхронного :

def do(coroutine):
    event_loop = asyncio.new_event_loop()
    asyncio.set_event_loop(event_loop)
    result = event_loop.run_until_complete(coroutine)
    asyncio.get_event_loop().close()
    return result

Проблема

«Проблема» заключается в том, чтоЯ не могу поместить with... as в do().

Я думал об использовании async with (я использую Python 3.6), но на самом деле у меня не может быть этого утверждения внутри синхронного метода и afaikПредставления Джанго должны быть синхронными.

Решения, которые я могу придумать

  • Сделать диспетчер контекста opened() синхронным и обернуть каждый асинхронный вызов в нем с помощью do ().Затем выведите синхронный управляемый дескриптор.Недостаток: закрытие дескриптора заблокировало бы остальную часть кода.Хотя мне все равно приходится ждать открытия (-> асинхронность не быстрее), от закрытия ничего не зависит, и асинхронность будет быстрее.
  • Создайте асинхронный метод для каждого представления и позвольте каждому синхронному представлению Djano запускать этоасинхронный метод, который содержит всю логику.Затем я мог бы использовать with async....as в этом асинхронном методе.Недостаток: массовое дублирование кода.

Вопрос

Как лучше всего справиться с этим?Django работает синхронно, но мои удаленные вызовы асинхронны?Где я должен построить мост?

Примечания

Я хочу использовать with...as, чтобы иметь RAII.Только представления должны открывать дескрипторы, и они также должны быть закрыты в их контексте.Если этот подход ошибочен, я открыт для улучшений.

...