Ожидать будущее / сопрограмма внутри цикла событий;вне сопрограммы - PullRequest
0 голосов
/ 31 октября 2019

У меня есть код с этой структурой:

def my_callback():
    loop = asyncio.get_event_loop()
    return loop.run_until_complete(my_coroutine_2())

async def my_coroutine_2():
    return await my_stuff.some_future

async def my_coroutine():
    not_my_code.library_function(my_callback)

Внутри my_callback, который library_function вызывает, мне нужно получить доступ и выполнить код сопрограммы.

Однако, run_until_complete выдает ошибку: Event loop already running!.

Возможно ли выполнить то, что описано выше?

То есть существует ли обычный вызов функции, который будетзаставить цикл обработки событий приостановить выполнение любой сопрограммы (т. е. вызывающего loop.run_until_complete()) и продолжить выполнение других сопрограмм (включая передаваемую в run_until_complete()), пока не будет завершена запрошенная сопрограмма, в этом случае обычная функция un-блоки?

Я думал, что, возможно, потоки могут помочь, но, насколько я понимаю, все сопрограммы должны принадлежать к одному потоку.

Как мне это сделать? Возможно ли это?

1 Ответ

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

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

Когда ваш обратный вызов вызывается из другого потока, он может использовать run_coroutine_threadsafe отправить сопрограмму в (все еще полностью функциональный) цикл событий и сообщить результат обратно в библиотеку:

async def my_coroutine():
    loop = asyncio.get_event_loop()
    await loop.run_in_executor(None, not_my_code.library_function,
                               lambda: my_callback(loop))

def my_callback(loop):
    return asyncio.run_coroutine_threadsafe(my_coroutine_2(), loop)
...