Удаление асинхронного загрязнения из Python - PullRequest
0 голосов
/ 28 октября 2019

Как удалить асинхронное безумие везде в такой программе?

import asyncio


async def async_coro():
    await asyncio.sleep(1)


async def sync_func_1():
    # This is blocking and synchronous
    await async_coro()


async def sync_func_2():
    # This is blocking and synchronous
    await sync_func_1()


if __name__ == "__main__":
    # Async pollution goes all the way to __main__
    asyncio.run(sync_func_2())

Мне нужно иметь 3 async маркера и asyncio.run на верхнем уровне, чтобы вызвать одну асинхронную функцию,Я предполагаю, что я делаю что-то не так - как я могу очистить этот код, чтобы он меньше использовал async?

FWIW, меня интересует в основном то, что я пишу API с использованием asyncio, а я нетхочу, чтобы мои пользователи слишком много думали о том, должны ли их функции быть def или async def в зависимости от того, используют ли они асинхронную часть API или нет.

Ответы [ 2 ]

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

После некоторого исследования один из ответов - вручную управлять циклом событий:

import asyncio


async def async_coro():
    await asyncio.sleep(1)


def sync_func_1():
    # This is blocking and synchronous
    loop = asyncio.get_event_loop()
    coro = async_coro()
    loop.run_until_complete(coro)


def sync_func_2():
    # This is blocking and synchronous
    sync_func_1()


if __name__ == "__main__":
    # No more async pollution
    sync_func_2()
0 голосов
/ 28 октября 2019

Если вы должны это сделать, я бы порекомендовал такой подход:

import asyncio, threading

async def async_coro():
    await asyncio.sleep(1)

_loop = asyncio.new_event_loop()
threading.Thread(target=_loop.run_forever, daemon=True).start()

def sync_func_1():
    # This is blocking and synchronous
    return asyncio.run_coroutine_threadsafe(async_coro(), _loop).result()

def sync_func_2():
    # This is blocking and synchronous
    sync_func_1()

if __name__ == "__main__":
    sync_func_2()

Преимущество этого подхода по сравнению с тем, в котором функции синхронизации запускают цикл событий, заключается в том, что он поддерживает вложение функций синхронизации. Он также запускает только один цикл обработки событий, так что, если базовая библиотека хочет настроить, например, фоновую задачу для мониторинга или чего-то подобного, она будет работать непрерывно, а не порождаться каждый раз заново.

...