Python 同步代码与异步代码的协作
发布时间 - 2026-01-29 00:00:00 点击率:次asyncio.run() 不能在已运行的事件循环中调用,应在顶层脚本中使用;在已有 loop 环境(如 Jupyter、FastAPI)中改用 create_task 或 run_until_complete;同步阻塞操作须替换为异步等价物或通过 run_in_executor 调用。
asyncio.run() 不能在已运行的事件循环中调用
这是最常见的协作崩溃点:你在 Jupyter、Django shell 或 FastAPI 的异步路由里,直接调用 asyncio.run(main()),会报 RuntimeError: asyncio.run() cannot be called from a running event loop。因为这些环境本身已启动了事件循环,asyncio.run() 试图再启一个,冲突了。
解决方法不是“换库”,而是判断上下文:
- 在顶层脚本(无现成 loop)中,用
asyncio.run()是安全且推荐的 - 在已有 loop 的环境里(如
ipython),改用asyncio.create_task()或asyncio.ensure_future()提交协程 - 需要从同步函数“等”一个异步结果时,用
asyncio.get_event_loop().run_until_complete(coro)(Python 3.7+ 兼容,但注意 loop 可能未启动)
同步阻塞调用(如 time.sleep、requests.get)会卡死整个异步流程
异步代码不是“多线程”,它依赖协程让出控制权。一旦混入同步阻塞操作,比如 time.sleep(5) 或 requests.get("https://httpbin.org/delay/5"),当前协程就真睡了 5 秒,其他任务全部挂起。
必须替换成异步等价物:
- 用
await asyncio.sleep(5)替代time.sleep(5) - 用
aiohttp.ClientSession或httpx.AsyncClient替代requests - 数据库操作必须用异步驱动(如
asyncpg、aiomysql、motor),不能用psycopg2或pymysql
如果实在绕不开同步库(比如某 SDK 只提供 sync 接口),可用 loop.run_in_executor() 把它扔进线程池执行,避免阻塞事件循环。
从同步函数安全调用异步函数的三种场景
实际项目中,常有老代码是同步的,但新模块是异步的,比如 Flask 路由要调用一个 async def fetch_data()。不能直接 fetch_data()(返回 coroutine 对象),也不能 await fetch_data()(语法错误,不在 async 函数里)。
对应策略取决于运行环境:
- 若确定当前无 event loop(如普通脚本),用
asyncio.run(fetch_data()) - 若不确定是否有 loop(如通用工具函数),先检查:
try: loop = asyncio.get_running_loop() except RuntimeError: loop = None,再按需选择loop.create_task()或asyncio.run() - 若在已知有 loop 的框架中(如 FastAPI 的
Dep),直接
ends
await fetch_data()—— 框架已确保你在 async 上下文里
async/await 与 threading 的混合使用容易引发状态混乱
有人想“既用 async 提高 I/O 并发,又用 threading 做 CPU 密集计算”,这没问题;但要注意:协程不绑定线程,asyncio 默认只在一个线程里调度所有协程。如果你在 run_in_executor 里修改了某个全局变量或类实例属性,而主线程的协程也同时读写它,就会出现竞态。
关键约束:
-
asyncio的原生对象(如asyncio.Queue、asyncio.Lock)只能在协程中 await,不能在线程里用 - 线程间共享数据,仍得用
threading.Lock、queue.Queue等传统同步原语 - 避免在 executor 中操作 event loop 相关对象(如
loop.call_soon_threadsafe是例外,但应尽量少用)
最稳妥的做法是:I/O 交给 async,CPU 密集交给 concurrent.futures.ProcessPoolExecutor(而非 ThreadPoolExecutor),彻底隔离内存空间。
# mysql
# python
# go
# 工具
# session
# ai
# 路由
# 解决方法
# django
# flask
# fastapi
# httpx
# ipython
# try
# 全局变量
# 循环
# 接口
# Event
# 线程
# 多线程
# 主线程
# 并发
# 对象
# 事件
# 异步
# jupyter
# 数据库
# https
# 你在
# 已有
# 能在
# 会报
# 这是
# 就会
# 运行环境
# 把它
# 三种
# 只在
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
如何制作新型网站程序文件,新型止水鱼鳞网要拆除吗?
香港服务器部署网站为何提示未备案?
jQuery中的100个技巧汇总
JavaScript如何操作视频_媒体API怎么控制播放
厦门模型网站设计制作公司,厦门航空飞机模型掉色怎么办?
家族网站制作贴纸教程视频,用豆子做粘帖画怎么制作?
QQ浏览器网页版登录入口 个人中心在线进入
齐河建站公司:营销型网站建设与SEO优化双核驱动策略
为什么要用作用域操作符_php中访问类常量与静态属性的优势【解答】
如何用好域名打造高点击率的自主建站?
手机网站制作与建设方案,手机网站如何建设?
企业网站制作这些问题要关注
Laravel怎么处理异常_Laravel自定义异常处理与错误页面教程
详解一款开源免费的.NET文档操作组件DocX(.NET组件介绍之一)
INTERNET浏览器怎样恢复关闭标签页_INTERNET浏览器标签恢复快捷键与方法【指南】
如何快速辨别茅台真假?关键步骤解析
网站图片在线制作软件,怎么在图片上做链接?
Laravel的契約(Contracts)是什么_深入理解Laravel Contracts与依赖倒置
香港服务器网站测试全流程:性能评估、SEO加载与移动适配优化
Laravel如何安装使用Debugbar工具栏_Laravel性能调试与SQL监控插件【步骤】
WordPress 子目录安装中正确处理脚本路径的完整指南
Zeus浏览器网页版官网入口 宙斯浏览器官网在线通道
,交易猫的商品怎么发布到网站上去?
中国移动官方网站首页入口 中国移动官网网页登录
手机钓鱼网站怎么制作视频,怎样拦截钓鱼网站。怎么办?
Laravel如何处理跨站请求伪造(CSRF)保护_Laravel表单安全机制与令牌校验
Angular 表单中正确绑定输入值以确保提交与验证正常工作
Laravel的HTTP客户端怎么用_Laravel HTTP Client发起API请求教程
Laravel任务队列怎么用_Laravel Queues异步处理任务提升应用性能
装修招标网站设计制作流程,装修招标流程?
如何在腾讯云服务器快速搭建个人网站?
Laravel如何使用集合(Collections)进行数据处理_Laravel Collection常用方法与技巧
Laravel如何处理文件上传_Laravel Storage门面实现文件存储与管理
rsync同步时出现rsync: failed to set times on “xxxx”: Operation not permitted
香港服务器建站指南:免备案优势与SEO优化技巧全解析
javascript基于原型链的继承及call和apply函数用法分析
Laravel如何生成URL和重定向?(路由助手函数)
如何用PHP工具快速搭建高效网站?
Python文件异常处理策略_健壮性说明【指导】
Laravel如何处理文件下载请求?(Response示例)
怎么制作一个起泡网,水泡粪全漏粪育肥舍冬季氨气超过25ppm,可以有哪些措施降低舍内氨气水平?
BootStrap整体框架之基础布局组件
Python结构化数据采集_字段抽取解析【教程】
大连网站制作费用,大连新青年网站,五年四班里的视频怎样下载啊?
Python图片处理进阶教程_Pillow滤镜与图像增强
矢量图网站制作软件,用千图网的一张矢量图做公司app首页,该网站并未说明版权等问题,这样做算不算侵权?应该如何解决?
Python文件操作最佳实践_稳定性说明【指导】
如何在宝塔面板中创建新站点?
悟空识字如何进行跟读录音_悟空识字开启麦克风权限与录音
php中::能调用final静态方法吗_final修饰静态方法调用规则【解答】


