
本文详解 asyncio 中事件循环的创建与启动机制,明确区分 asyncio.run()(高阶自动管理)与 asyncio.new_event_loop() + 手动配置(低阶精细控制)两类方式,并通过可运行示例说明核心流程与关键注意事项。
本文详解 asyncio 中事件循环的创建与启动机制,明确区分 `asyncio.run()`(高阶自动管理)与 `asyncio.new_event_loop()` + 手动配置(低阶精细控制)两类方式,并通过可运行示例说明核心流程与关键注意事项。
在 Python 的 asyncio 框架中,事件循环(Event Loop)是异步程序的执行引擎,所有协程、任务和回调均在其上调度运行。理解其创建与启动逻辑,是掌握异步编程的关键基础。
✅ 事件循环的创建方式
高阶 API(推荐用于大多数应用):asyncio.run(coro) 是首选入口。它内部自动创建并管理事件循环——默认调用 asyncio.new_event_loop() 创建新实例(若指定了 loop_factory,则使用该工厂函数)。你无需手动干预循环生命周期,run() 在执行完毕后还会自动关闭循环并清理资源。
低阶 API(适用于高级定制场景):直接调用 asyncio.new_event_loop() 可显式创建一个全新事件循环对象(如 SelectorEventLoop 或 ProactorEventLoop)。但注意:它仅创建,不设置也不运行——你需要后续调用 asyncio.set_event_loop(loop) 将其绑定到当前线程,并自行调用运行方法。
⚠️ 特别注意:asyncio.get_event_loop() 从不创建新循环!它仅返回当前线程中已设置的事件循环;若尚未设置,则返回策略(get_event_loop_policy().get_event_loop())提供的默认循环(可能复用或新建,取决于策略实现)。在未调用 run() 或 set_event_loop() 的上下文中直接调用 get_event_loop() 可能引发 RuntimeError(尤其在多线程环境中)。
立即学习“Python免费学习笔记(深入)”;
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
▶️ 事件循环的启动方式
- asyncio.run(coro):一站式启动——创建 → 设置 → 提交任务 → 运行至完成 → 关闭循环。
- 手动模式下,需调用循环对象的方法:
- loop.run_until_complete(future):运行至指定协程/任务完成,返回结果(最常用);
- loop.run_forever():持续运行,直到显式调用 loop.stop()(适用于长期服务,如 Web 服务器)。
? 实用示例对比
以下两个等效示例均获取模拟数据,清晰体现高阶与低阶 API 的差异:
✅ 高阶方式(简洁安全)
import asyncio
async def get_data():
data = [{"name": "Jane", "age": 19}, {"name": "John", "age": 24}]
await asyncio.sleep(1) # 模拟 I/O 延迟
return data
if __name__ == "__main__":
result = asyncio.run(get_data())
print(result) # [{'name': 'Jane', 'age': 19}, {'name': 'John', 'age': 24}]? 低阶方式(精细控制)
import asyncio
async def get_data():
data = [{"name": "Jane", "age": 19}, {"name": "John", "age": 24}]
await asyncio.sleep(1)
return data
def main():
# 显式创建并设置事件循环
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:
# 创建任务并运行
task = loop.create_task(get_data())
loop.run_until_complete(task)
print(task.result())
finally:
# 必须手动关闭循环(避免资源泄漏)
loop.close()
if __name__ == "__main__":
main()⚠️ 关键注意事项
- 避免混用:不要在 asyncio.run() 内部再调用 get_event_loop() 或手动创建循环——run() 已独占管理,重复操作会导致未定义行为。
- 线程安全:每个线程默认拥有独立事件循环;跨线程访问需显式传递 loop 对象,不可依赖 get_event_loop()。
- 资源清理:低阶模式下务必调用 loop.close(),否则可能导致文件描述符泄漏或进程无法退出。
- Python 3.10+ 建议:优先使用 asyncio.run(),它已修复早期版本的循环复用问题,更健壮可靠。
掌握事件循环的“谁创建、谁启动、谁关闭”三原则,是写出稳定、高效 asyncio 应用的第一步。

















