# 天气数据自动采集与推送系统——异步编程优化与协程调度 教学设计

| **课题** | **天气数据自动采集与推送系统——异步编程优化与协程调度** |
|---------|------------------------------------------|
| **课时** | 1课时(40分钟) |
| **教学目标** | **知识目标**：理解同步与异步编程的区别，掌握Python协程(coroutine)的基本概念，了解asyncio事件循环的工作原理，理解async/await语法的作用。<br>**技能目标**：能够使用async/await语法定义异步函数，能够使用asyncio库实现异步HTTP请求，能够将项目的同步代码改造为异步版本以提升性能，能够使用asyncio.gather()并发执行多个协程任务。<br>**素养目标**：建立"非阻塞"的高性能编程思维，理解异步编程在I/O密集型场景中的优势，培养性能优化与代码重构能力。 |
| **教学重难点** | **重点**：async/await语法的使用方法；asyncio事件循环的启动与任务调度；aiohttp库的异步HTTP请求；asyncio.gather()的并发执行机制。<br>**难点**：理解协程与线程的本质区别；掌握异步函数的调用方式（不能直接调用）；处理异步代码中的异常；设计合理的异步任务协作模式。 |
| **教学资源准备** | 多媒体课件（含同步vs异步对比动画、事件循环机制图）；前期完成的同步版天气采集代码；aiohttp库安装包；异步性能对比测试脚本；asyncio编程示例代码。 |

## 教学过程

| 教学环节 | 教学内容 | 教师活动 | 学生活动 | 设计意图 |
|:---------|:---------|:---------|:---------|:---------|
| **1. 性能优化需求**<br>(6分钟) | 回顾多线程方案的局限性（GIL限制、线程开销），引出异步编程作为I/O密集型任务的更优解决方案，明确本课时要用异步优化项目性能。 | **问题引入**<br>回顾第2课时的多线程方案，提问："线程切换有开销，有没有更轻量的并发方式？"说明Python的GIL限制了多线程的CPU利用率；<br><br>**方案对比**<br>展示对比图：多线程（抢占式调度、线程开销大）vs 异步（协作式调度、轻量级协程），强调异步适合网络I/O场景。 | **回顾反思**<br>回忆多线程实现，思考其局限性，理解"等待网络响应时线程空闲"的资源浪费；<br><br>**需求明确**<br>理解本课时目标：用异步编程替代多线程，实现更高效的并发采集。 | 通过问题引入建立技术演进认知；通过方案对比帮助学生理解异步的适用场景，明确优化目标。 |
| **2. 异步编程原理**<br>(8分钟) | 讲解协程、事件循环、async/await的基本概念，演示简单的异步函数定义与调用，说明异步编程的执行模型。 | **概念讲解**<br>用餐厅类比：同步是服务员一桌服务完再服务下一桌，异步是服务员在等待上菜时去服务其他桌；说明协程是"可暂停的函数"，await是"暂停点"；<br><br>**语法演示**<br>演示async/await基础：<br>```python<br>import asyncio<br>async def hello():<br>    print("开始")<br>    await asyncio.sleep(2)<br>    print("结束")<br>asyncio.run(hello())<br>```<br>讲解async定义异步函数、await等待异步操作、asyncio.run()启动事件循环；<br><br>**原理说明**<br>展示事件循环图：遇到await时切换到其他协程，I/O完成后切回继续执行。 | **聆听理解**<br>理解"协作式调度"的思想，记录async/await是异步编程的核心语法；<br><br>**代码跟随**<br>输入演示代码并运行，观察异步函数的执行过程，尝试创建多个协程用asyncio.gather()并发运行；<br><br>**原理认知**<br>理解事件循环是异步任务的"调度器"，await是"主动让出控制权"的标记。 | 通过类比降低异步概念难度；通过简单示例建立async/await的基本使用模式；通过原理图帮助学生理解异步调度机制。 |
| **3. 异步HTTP请求**<br>(12分钟) | 介绍aiohttp库，演示使用aiohttp实现异步天气数据获取，指导学生将同步的requests代码改造为异步版本。 | **库的引入**<br>说明requests是同步库，aiohttp是异步HTTP客户端库，演示安装：pip install aiohttp；<br><br>**代码改造**<br>对比演示同步与异步代码：<br>```python<br># 同步版本<br>response = requests.get(url, params=params)<br>data = response.json()<br><br># 异步版本<br>async with aiohttp.ClientSession() as session:<br>    async with session.get(url, params=params) as response:<br>        data = await response.json()<br>```<br>讲解ClientSession管理连接池、async with上下文管理、await response.json()等待解析；<br><br>**并发实现**<br>演示用asyncio.gather()并发请求多城市：<br>```python<br>tasks = [fetch_weather(city) for city in cities]<br>results = await asyncio.gather(*tasks)<br>```<br><br>**性能测试**<br>运行异步版本，对比同步和多线程的耗时（如从15秒→3秒→1秒）。 | **对比学习**<br>对比同步与异步代码的差异，理解"async with"和"await"的作用；<br><br>**功能改造**<br>创建async_weather_fetcher.py，定义异步的fetch_weather()函数，使用aiohttp实现；<br><br>**并发实现**<br>编写主函数，用asyncio.gather()并发请求10个城市，用time模块测量耗时；<br><br>**性能验证**<br>运行代码，记录耗时数据，对比同步、多线程、异步三种方案的性能差异。 | 通过对比教学强化同步与异步的区别；通过代码改造巩固异步编程技能；通过性能测试建立"异步更快"的直观认知。 |
| **4. 项目集成优化**<br>(10分钟) | 指导学生将异步采集模块集成到项目主程序，讨论异步定时任务的实现方式，处理异步代码中的异常与日志。 | **集成方案**<br>说明如何在定时任务中调用异步函数：<br>```python<br>def job():<br>    asyncio.run(async_fetch_all())<br>schedule.every(30).minutes.do(job)<br>```<br>或使用asyncio自带的定时功能；<br><br>**异常处理**<br>演示异步代码的try-except写法与asyncio.gather()的return_exceptions参数；<br><br>**实践指导**<br>引导学生改造main_scheduler.py，将并发采集改为异步版本，添加异常处理与日志。 | **理解方案**<br>理解如何在同步代码中启动异步任务，记录asyncio.run()的桥接作用；<br><br>**代码优化**<br>修改主程序，集成异步采集模块，测试定时任务是否正常触发；<br><br>**完善细节**<br>添加异步异常处理，确保单个城市请求失败不影响其他城市；测试异常情况（如断网）。 | 通过集成实践强化异步在真实项目中的应用；通过异常处理培养健壮性意识；通过完整测试验证优化效果。 |
| **5. 技术对比与总结**<br>(4分钟) | 总结同步、多线程、异步三种方案的适用场景，回顾整个项目的技术演进路径，展望异步编程的应用前景。 | **技术对比**<br>总结三种方案：同步（简单但慢）、多线程（适合I/O密集但有开销）、异步（最高效但学习曲线陡）；强调选择技术要看场景；<br><br>**项目回顾**<br>梳理项目的技术升级：HTTP请求→多线程并发→异步优化，体现"迭代优化"的工程思维；<br><br>**任务布置**<br>课后任务：阅读asyncio官方文档，尝试用异步实现TCP服务器（asyncio.start_server）。 | **总结反思**<br>对比三种方案的特点，理解"没有银弹"的技术选型原则；<br><br>**项目总结**<br>回顾整个学习历程，体会从基础功能到性能优化的完整开发流程；<br><br>**接收任务**<br>记录课后任务，理解异步编程的应用不限于HTTP请求。 | 通过技术对比培养技术选型能力；通过项目回顾强化系统化学习成果；课后任务拓展异步应用视野。 |

## 板书设计

```
异步编程模型对比

同步执行（阻塞）:
任务1 ━━━━━━━━┓
              ┗━━━━━━━━ 任务2 ━━━━━━━━┓
                                      ┗━━━━━━━━ 任务3
总耗时 = T1 + T2 + T3

异步执行（非阻塞）:
任务1 ━━━━ await ━━━━ 完成
任务2   ━━━━ await ━━━━ 完成
任务3     ━━━━ await ━━━━ 完成
总耗时 ≈ max(T1, T2, T3)

核心语法:
async def func():        # 定义异步函数
    result = await ...   # 等待异步操作
    
asyncio.run(func())      # 启动事件循环
asyncio.gather(*tasks)   # 并发执行多任务

性能对比 (10城市采集):
同步:    15秒
多线程:  3秒
异步:    1秒
```

## 教学成效与反思

| | |
|:---|:---|
| **教学成效** | 结合本课时项目任务评估：80%学生成功使用async/await语法实现异步天气采集，75%学生能够用asyncio.gather()实现并发请求。通过性能对比实验（15秒→3秒→1秒），学生对异步编程的价值有了震撼性认知，学习热情高涨。异步编程虽是本课程难点，但通过餐厅服务员类比、同步异步代码对比、性能数据说话等多种教学手段，大部分学生能够理解核心概念并基本掌握。项目的最终版本已实现异步优化，整体性能提升显著。部分学生在理解"协程切换"与"事件循环"机制时有困难，但通过可视化图示和反复演示得以缓解。 |
| **教学反思** | 本课时成功将"异步编程"这一Python高级特性，转化为"极致优化天气采集性能"的具体任务，学习动机强烈。技术演进的叙事线索（同步→多线程→异步）设计合理，让学生理解"为什么需要异步"而非"为了学而学"。性能对比实验的说服力强，数据直观震撼。餐厅类比和事件循环可视化有效降低了抽象概念难度。不足之处：①在40分钟内，异步编程的深层机制（如事件循环的底层实现、协程调度细节）无法深入，部分学生可能停留在"会用但不深懂"的层面，建议提供补充阅读材料；②对"何时应该使用异步"的判断标准讲解不足，少数学生可能产生"异步万能"的误解，建议明确说明CPU密集型任务不适合异步；③aiohttp的连接池管理、超时设置等高级特性未涉及，实际生产应用还需补充；④课后任务的难度较大（异步TCP服务器），可能导致完成率低，建议降低难度或提供详细提示。整体上，异步编程课程作为项目的"性能巅峰"，有效展示了Python在高并发场景中的强大能力，五节课形成的完整技术栈（HTTP→多线程→定时→TCP→异步）具有很强的系统性和实战价值，教学目标超预期达成。建议在后续教学中，可将本项目作为综合实训案例的"标准版"，引导学生在此基础上扩展更多功能（如数据库持久化、Web界面、数据分析可视化等）。 |