asyncio事件循环可以在后台运行而不挂起Python解释器吗?

Jef*_*own 26 python concurrency python-asyncio

对于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事件循环,以便我可以在解释器中输入命令?

dan*_*ano 42

您可以在后台线程中运行事件循环:

>>> 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
Run Code Online (Sandbox Code Playgroud)

请注意,您必须调用asyncioasyncio.set_event_loop,否则你会得到一个错误,指出当前线程没有一个事件循环.

如果要与主线程中的事件循环进行交互,则需要坚持loop调用.

虽然这种方法是在解释器中进行实验的好方法,但在实际程序中,您可能希望所有代码在事件循环中运行,而不是引入线程.

  • @dano"你可能希望*所有*你的代码在事件循环中运行,而不是引入线程" - 你会为你拥有大型代码库但你不想/不想要的情况做出例外吗?完全转换为异步风格; 同时,你确实想要一些`asyncio`的功能(比如预定的后台操作)?似乎在后台线程中运行事件循环将完全适合这种情况,但我可能会遗漏一些隐藏的复杂情况. (4认同)
  • 非常感谢。有人 [其他地方](http://monome.org/community/discussion/comment/208744#Comment_208744) 说不要混合线程和 asyncio。你不同意吗?该进程的后台是一个 OSC 服务器。从口译员那里我会告诉它要发送什么信号。Python 进程将是轻量级的,向执行所有音频数学运算的合成器发送指令(可能每秒 20 个包)。鉴于这种动机,您是否继续建议将所有内容都放在主循环中? (2认同)
  • @max 是的,我认为没关系。你只需要小心在 `asyncio` 事件循环线程和你运行的任何其他线程之间共享数据。 (2认同)

zer*_*one 7

使用Python 3.8,您可以使用新的asyncio REPL。

$ 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())
Run Code Online (Sandbox Code Playgroud)

  • 运行时错误:没有运行事件循环。看起来需要创建一个新循环,其中loop = asyncio.get_event_loop(),然后task = loop.create_task(greet_every_two_seconds()) (6认同)
  • @avenmia 在“await”之后删除“from” (3认同)