可以在不暂停 Python 解释器的情况下在后台运行异步事件循环吗?
Posted
技术标签:
【中文标题】可以在不暂停 Python 解释器的情况下在后台运行异步事件循环吗?【英文标题】:Can an asyncio event loop run in the background without suspending the Python interpreter? 【发布时间】:2014-10-09 05:03:09 【问题描述】: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 或更高版本,则应使用 asyncio
repl,如 zeronone's answer 中所述。如果使用 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
请注意,您必须在loop
上调用asyncio.set_event_loop
,否则您会收到一条错误消息,指出当前线程没有事件循环。
如果您想从主线程与事件循环进行交互,您需要坚持使用loop.call_soon_threadsafe
调用。
虽然这种事情是在解释器中试验的好方法,但在实际程序中,您可能希望所有代码在事件循环中运行,而不是引入线程。 p>
【讨论】:
非常感谢。有人elsewhere 说不要混合线程和异步。你不同意吗?该进程的后台将是一个 OSC 服务器。从口译员那里,我会告诉它要发送什么信号。 Python 进程将是轻量级的,向执行所有音频数学运算的合成器发送指令(可能每秒 20 个包)。鉴于这种动机,您是否继续建议将所有内容都放在主循环中? @user916142 好吧,通常使用像asyncio
这样的异步框架的全部意义在于避免使用线程。如果您总是要在交互式解释器中运行此代码,那么我想这是有道理的。但通常我会说你应该实现一个 asyncio
Procotol
或 Stream
来处理传入的网络连接,然后告诉它通过网络请求发送什么信号。
Here 是我的一些代码,用于处理串行、WebSockets、stdin 和带有 asyncio 的 OSC 上的消息。它不允许您访问解释器,但我的解决方案是使用回调处理键盘输入:loop.add_reader(sys.stdin.fileno(), read_stdin)
@dano “你可能希望 all 你的代码在事件循环中运行,而不是引入线程”——你会为你有的情况例外吗?您不能/不想完全转换为异步样式的大型代码库;同时,您是否想要asyncio
的某些功能(例如预定的后台操作)?似乎在后台线程中运行事件循环非常适合这种情况,但我可能会遗漏一些隐藏的并发症。
@max 是的,我认为没关系。您只需要小心在asyncio
eventloop 线程和您正在运行的任何其他线程之间共享数据。【参考方案2】:
在 Python 3.8 中,您可以使用新的 asyncio REPL。
$ python -m asyncio
>>> async def greet_every_two_seconds():
... while True:
... print('Hello World')
... await 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())
【讨论】:
我得到“SyntaxError: invalid syntax” 指向“await from asyncio.sleep(2) 中的 from。我目前正在运行 python 3.8 @avenmia 删除from
之后的await
RuntimeError: 没有正在运行的事件循环。看起来需要使用 loop = asyncio.get_event_loop() 然后创建一个新循环 task = loop.create_task(greet_every_two_seconds())以上是关于可以在不暂停 Python 解释器的情况下在后台运行异步事件循环吗?的主要内容,如果未能解决你的问题,请参考以下文章
我可以在不使用 Unity 的情况下在 Android VR 视图中添加像 youtube 这样的凝视控制功能吗?
是否可以在不安装 Python 的情况下在 Windows 上安装 Robot Framework?
是否可以在不使用 python 移动终端行的情况下在同一位置打印“for循环”表?
如何在不定义任何限制的情况下在 python 中获取任意数量的输入?