Python异步系统学习路线第259讲_核心原理与实战案例详解【教程】

发布时间 - 2025-12-26 00:00:00    点击率:
asyncio.run()只能调用一次,因其内部创建并关闭事件循环;await后必须是真正的awaitable对象,如asyncio.sleep而非time.sleep;create_task()实现并发调度,而直接await则顺序执行。

这标题看着像教程,实际不是入门向内容——asyncio 的核心原理和实战案例,真正卡住人的从来不是语法,而是事件循环怎么调度、协程对象怎么挂起、await 底层怎么触发状态切换。

asyncio.run() 为什么只能调用一次?

因为 asyncio.run() 内部会创建新事件循环、运行完就关闭。再调用就会报 RuntimeError: asyncio.run() cannot be called from a running event loop

  • 开发时别在 Jupyter 或已启动 asyncio 的环境中反复执行 asyncio.run(main())
  • 想多次运行,改用 asyncio.get_event_loop().run_until_complete(main())(注意:Python 3.10+ 推荐用 asyncio.new_event_loop() + set_event_loop() 显式管理)
  • asyncio.run() 隐含了 loop.close(),关闭后无法复用

await 后面必须是 awaitable,但不是所有“能 await 的东西”都安全

比如 await time.sleep(1) 看似合理,实则阻塞整个事件循环——time.sleep 是同步阻塞函数,根本不是 awaitable。

  • 正确做法是用 await asyncio.sleep(1)
  • 第三方库如 requests 没有异步支持,直接 await requests.get(...) 会报 TypeError: object Response can't be used in 'await' expression
  • 数据库操作要用 aiomysqlasyncpgmotor 这类原生 async 驱动,不能套壳 await loop.run_in_executor(..., sqlite3.connect)(虽可行但掩盖问题)

asyncio.create_task() 和直接 await 的区别不只是“后台执行”

关键在于调度时机:await coro 是立即进入并阻塞等待完成;asyncio.create_task(coro) 把协程注册进事件循环,当前函数可继续往下走,下次循环 tick 才开始执行。

import asyncio

async def say(what, delay):
    await asyncio.sleep(delay)
    print(what)

async def main():
    task1 = asyncio.create_task(say("hello", 2))
    task2 = asyncio.create_task(say("world", 1))
    print("tasks created")
    await task1
    await task2

asyncio.run(main())

输出顺序是:tasks created → world → hello。如果写成 await say("hello", 2),那 say("world", 1) 就得等 2 秒后才开始。

async with 和 async for 不是语法糖,它们依赖 __aenter__/__aexit__ 和 __aiter__/__anext__

没实现这些方法的对象,哪怕加了 async 前缀,也不能用于 async with。常见坑:

  • aiofiles.open() 可以,open() 不行
  • aiomysql.Pool 支持 async with pool.acquire(),但自己写的普通上下文管理器加 async 不等于自动支持
  • async for line in file: 要求 file 实现 __aiter__,不是所有文件对象都满足(比如 io.StringIO 就不行)
真正难的不是写 async def,是理解「谁在什么时候让出控制权」「事件循环在哪一刻把哪个协程切回来」。调试时多打 print(f"at {inspect.currentframe().f_lineno}"),比看文档更快定位挂起点。


# mysql  # python  # ai  # 区别  # 为什么 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Android自定义控件实现温度旋转按钮效果  php中::能调用final静态方法吗_final修饰静态方法调用规则【解答】  LinuxShell函数封装方法_脚本复用设计思路【教程】  微信小程序 canvas开发实例及注意事项  使用spring连接及操作mongodb3.0实例  电商网站制作多少钱一个,电子商务公司的网站制作费用计入什么科目?  java中使用zxing批量生成二维码立牌  Laravel如何实现登录错误次数限制_Laravel自带LoginThrottles限流配置【方法】  Win11搜索栏无法输入_解决Win11开始菜单搜索没反应问题【技巧】  Laravel如何实现用户注册和登录?(Auth脚手架指南)  Laravel怎么做缓存_Laravel Cache系统提升应用速度的策略与技巧  制作企业网站建设方案,怎样建设一个公司网站?  Laravel怎么连接多个数据库_Laravel多数据库连接配置  活动邀请函制作网站有哪些,活动邀请函文案?  laravel服务容器和依赖注入怎么理解_laravel服务容器与依赖注入解析  三星、SK海力士获美批准:可向中国出口芯片制造设备  通义万相免费版怎么用_通义万相免费版使用方法详细指南【教程】  JavaScript 输出显示内容(document.write、alert、innerHTML、console.log)  Laravel怎么生成URL_Laravel路由命名与URL生成函数详解  如何快速搭建个人网站并优化SEO?  Laravel怎么实现搜索功能_Laravel使用Eloquent实现模糊查询与多条件搜索【实例】  免费视频制作网站,更新又快又好的免费电影网站?  如何自定义safari浏览器工具栏?个性化设置safari浏览器界面教程【技巧】  HTML5空格和margin有啥区别_空格与外边距的使用场景【说明】  HTML透明颜色代码怎么让图片透明_给img元素加透明色的技巧【方法】  Linux后台任务运行方法_nohup与&使用技巧【技巧】  Laravel怎么上传文件_Laravel图片上传及存储配置  如何在沈阳梯子盘古建站优化SEO排名与功能模块?  如何快速建站并高效导出源代码?  mc皮肤壁纸制作器,苹果平板怎么设置自己想要的壁纸我的世界?  详解Nginx + Tomcat 反向代理 负载均衡 集群 部署指南  高端智能建站公司优选:品牌定制与SEO优化一站式服务  javascript日期怎么处理_如何格式化输出  如何用景安虚拟主机手机版绑定域名建站?  javascript中的try catch异常捕获机制用法分析  如何用wdcp快速搭建高效网站?  JavaScript中如何操作剪贴板_ClipboardAPI怎么用  历史网站制作软件,华为如何找回被删除的网站?  如何在IIS服务器上快速部署高效网站?  Laravel怎么实现观察者模式Observer_Laravel模型事件监听与解耦开发【指南】  头像制作网站在线观看,除了站酷,还有哪些比较好的设计网站?  HTML5空格在Angular项目里怎么处理_Angular中空格的渲染问题【详解】  如何在宝塔面板中创建新站点?  html5audio标签播放结束怎么触发事件_onended回调方法【教程】  网站制作价目表怎么做,珍爱网婚介费用多少?  laravel怎么为应用开启和关闭维护模式_laravel应用维护模式开启与关闭方法  海南网站制作公司有哪些,海口网是哪家的?  Laravel如何配置和使用队列处理异步任务_Laravel队列驱动与任务分发实例  JS碰撞运动实现方法详解  Laravel如何优雅地处理服务层_在Laravel中使用Service层和Repository层