asyncio事件循环能在后台运行而不暂停Python解释器吗?

42 投票
3 回答
74406 浏览
提问于 2025-04-26 12:02

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的事件循环能不能在后台运行,这样我就可以继续在解释器里输入命令?

暂无标签

3 个回答

0

@raisyn

ipython 中,这个是可以正常工作的:

import asyncio
from traitlets.config.application import Application

async def greet_every_two_seconds():
    while True:
        print('Hello World')
        await asyncio.sleep(2)
        
# Create coroutine
coro = greet_every_two_seconds()

# Create and get an adequate asyncio event loop
Application.instance().shell.enable_gui('asyncio')
loop = asyncio.get_event_loop()

loop.create_task(coro)

43

在Python 3.8中,你可以使用新的asyncio交互式命令行工具。

$ 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())
64

编辑:

如果你使用的是 Python 3.8 或更高版本,建议使用 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
# 2 second later
# Hello World

请注意,你必须loop 上调用 asyncio.set_event_loop,否则你会遇到错误,提示当前线程没有事件循环。

如果你想从主线程与事件循环进行交互,你需要使用 loop.call_soon_threadsafe 这个方法。

虽然这种方式在交互式环境中实验是可以的,但在实际程序中,你可能希望所有代码都在事件循环中运行,而不是引入线程。

撰写回答