Может ли цикл события asyncio работать в фоновом режиме без приостановки интерпретатора Python?

Документация для asyncio дает два примера, как печатать "Hello World" каждые две секунды: https://docs.python.org/3/library/asyncio-eventloop.html#asyncio-hello-world-callback https://docs.python.org/3/library/asyncio-task.html#asyncio-hello-world-coroutine

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

Ответы

Ответ 1

Изменить:

Если вы используете Python 3.8 или выше, вы должны использовать repl asyncio, как описано в ответе zeronone. Если вы используете версию 3.7 или ниже, вы можете использовать этот ответ.


Вы можете запустить цикл обработки событий в фоновом потоке:

>>> import asyncio
>>> 
>>> @asyncio.coroutine
... def greet_every_two_seconds():
...     while True:
...         print('Hello World')
...         yield from asyncio.sleep(2)
... 
>>> def loop_in_thread(loop):
...     asyncio.set_event_loop(loop)
...     loop.run_until_complete(greet_every_two_seconds())
... 
>>> 
>>> loop = asyncio.get_event_loop()
>>> import threading
>>> t = threading.Thread(target=loop_in_thread, args=(loop,))
>>> t.start()
Hello World
>>> 
>>> Hello World

Обратите внимание, что вы должны вызвать asyncio.set_event_loop на loop, в противном случае вы получите сообщение о том, что текущий поток не имеет цикла обработки событий.

Если вы хотите взаимодействовать с циклом событий из основного потока, вам нужно придерживаться loop.call_soon_threadsafe вызовов.

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

Ответ 2

В Python 3.8 вы можете использовать новый REPL asyncio.

$ python -m asyncio
>>> async def greet_every_two_seconds():
...     while True:
...         print('Hello World')
...         await from asyncio.sleep(2)
...
>>> # run in main thread (Ctrl+C to cancel)
>>> await greet_every_two_seconds()
...
>>> # run in background
>>> asyncio.create_task(greet_every_two_seconds())