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