ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Python实战:用不到100行代码实现个性化彩色天气问候程序

Python实战:用不到100行代码实现个性化彩色天气问候程序 最近在准备AI课程的练习素材一直想找一个既能讲清楚Python基础语法、又能让学生一眼看到有趣结果的例子。前后试过猜数字、爬虫抓标题效果都一般。最后定了这个方案输入你的名字和城市程序自动打印一段彩色个性化问候顺便把当地实时天气也带上整个代码不到一百行却把输入输出、函数、字典映射、异常处理、第三方库、API调用全串起来了。这个项目挂在AI课程的“综合练习”阶段超级合适。学生写完代码运行起来看到自己名字以彩色出现还有实时天气那种“这玩意真的在我电脑上跑起来了”的兴奋感比刷二十道语法题都管用。对自学Python的人来说这也是一个很好的“第一个有点用的程序”模板——你能看懂它、改它、塞进自己的工具箱。下面我把整个项目的设计思路、代码拆解、踩坑记录全部写出来想自用还是想拿去当教学案例都行。1. 项目背景与设计思路1.1 为什么选“名字城市天气”这个组合AI课程里给学生布置综合练习题我一直坚持一个原则要能立刻看到反馈要和真实世界有关系。打印九九乘法表符合第一条不符合第二条爬一个新闻标题符合第二条但反爬、解析、乱码一堆破事新手很容易卡住。我需要一个“看起来不难但五脏俱全”的项目。“名字城市天气”赢在哪输入只有两个普通的信息输出却是一段带着温度的问候语。学生输入自己的名字看到程序叫自己“林晓”再输入城市看到上海现在的气温这种“程序认识我、程序知道世界”的体验是极好的激励。而且它天生带扩展空间你可以加穿衣建议可以加多个城市对比可以给不同天气配不同颜色后面想往哪发展都顺。另一个现实原因是成本。免费且不用注册的天气接口有调用学习成本极低不用担心学生人手一个API key造成滥用。这个项目把“别人提供的服务怎么集成进来”这件事讲清楚了而这恰恰是AI课程里非常重要的一个素养——不是所有功能都要自己造轮子。1.2 技术选型天气数据从哪来天气数据的来源是整个项目的核心决策。当时我列了个对比清单方案是否需要Key是否需要注册返回中文新手友好度Open-Meteo不需要不需要支持高高德开放平台需要需要支持中和风天气需要需要支持中心知天气需要需要支持中如果有人问我为什么不选国内平台我会说不是不好而是课程场景下每个学生都去注册一个key排队、审核、限额一堂课半小时就耗完了。Open-Meteo不需要任何认证拿到经纬度就能查天气全球范围都覆盖而且支持中文城市名解析刚合适。这里要拆分两个接口。Open-Meteo的天气查询接收的是经纬度坐标不是城市名所以要先通过它的地理编码接口把“上海”变成“纬度31.23经度121.47”再用这个坐标去拿天气数据。逻辑上就像你先查邮编再寄信两个动作分开。代码里体现为两个函数职责清晰也方便以后替换成其他服务。1.3 彩色输出终端也能有视觉温度为什么非得搞彩色输出说实话最初版没有色彩纯黑底白字的问候语学生看完反应平淡。加上颜色之后晴天是亮黄色雨天是蓝色雪天是青色整个终端像一个迷你天气仪表盘观感完全不同。这个“视觉反馈”的成本极低但带来的体验提升非常大。原理不复杂。终端里有一种叫ANSI转义序列的东西本质是往标准输出里塞一串特殊字符比如\033[31m表示红色后面的文字都会变红直到遇到\033[0m复位。Python的print天生支持输出这些字符不需要额外库。但Windows老版本终端不支持所以我在Windows下调用colorama.init()做兼容它会把ANSI转义序列自动翻译成Windows API调用。注意这个库只在你用Windows而且遇到颜色显示异常时才必须其他场景可有可无。2. 核心环节拆解与代码落地2.1 城市名转坐标一条隐藏的分支前面提到天气接口只要经纬度所以第一步是“地点解析”。Open-Meteo的地理解析接口长这样url https://geocoding-api.open-meteo.com/v1/search params { name: city_name, count: 1, language: zh, format: json } resp requests.get(url, paramsparams, timeout10) data resp.json()返回结果里results[0]就是最匹配的城市里面包含latitude和longitude。这里有个细节count1只取最匹配的一条是因为很多城市存在重名比如“中山”在广东和台湾都有取第一条至少保证程序不崩。如果你教学生可以用个循环把results里的所有候选城市都打印出来让用户自己选这是很好的交互扩展点。实际跑的时候有个坑中文城市名有时能解析出来有时解析不到。因为地理编码服务对中文的支持并不完美这时候我建议学生在自己的代码里加一个“别名映射表”最常用的是把拼音也接上。比如CITY_ALIAS { 上海: shanghai, 北京: beijing, 广州: guangzhou, }查不到中文名就自动换上拼音再查一次。这个兜底逻辑在课程里可以单独讲一遍因为它就是“容错设计”的启蒙案例。2.2 天气码与中文描述的映射拿到坐标后调用天气接口url https://api.open-meteo.com/v1/forecast params { latitude: lat, longitude: lon, current: temperature_2m,relative_humidity_2m,weather_code,wind_speed_10m, timezone: Asia/Shanghai }返回的current里有一个weather_code这是WMO世界气象组织定义的天气现象代码纯数字。我需要把代码翻译成中文。这个翻译用字典搞定是Python里最直观的映射方式天气码含义推荐颜色0、1晴、以晴为主黄2、3多云、阴白45、48雾、冻雾白51、53、55毛毛雨系列蓝61、63、65小雨、中雨、大雨蓝71、73、75小雪、中雪、大雪青80、81、82阵雨系列蓝95雷暴蓝这个表直接放在代码里就是一个全局字典WEATHER_CODE_MAP。天气码一来中文描述和颜色一起确定。我特意把颜色选择也做成一个函数对着天气码给出颜色名这样以后想扩展比如“雷暴显示红色”就只改一处。2.3 问候语生成按时间和温度调整问候语不能写死否则每个人看到的都一样这就失去“个性化”的意义了。我的做法分两层第一层看时间第二层看气温。时间判断用datetime.now().hour分成几个区间深夜、清晨、上午、中午、下午、晚上。不同区间用不同的开头词“早上好”“下午好”这种。第二层看温度给一条穿衣建议比如超过30度提醒防暑低于0度提醒保暖。这两层信息拼起来就成了一个看着很“懂你”的问候下午好林晓你在上海当前天气小雨气温18℃相对湿度82%风速11km/h。温度有点凉记得加件外套。愿你今天心情也像天气一样清爽这里的语气词“愿你今天心情也像天气一样清爽”是我故意留的它让程序不再像机械报表更像一个真人朋友在说话。如果你想让学生改动可以让他们自己写一句结尾祝福看看谁的文案更有意思课堂气氛一下就活了。3. 完整实现与运行效果3.1 环境准备与依赖安装拿这个项目做教学环境准备越简单越好。我推荐Windows笔记本上用VSCodePython3.8以上都行不需要虚拟环境直接装两个包pip install requests pip install coloramarequests是HTTP客户端封装了所有网络请求细节colorama只在Windows下处理ANSI转义序列兼容Linux和macOS终端原生支持不装也能跑。如果你用PyCharm安装路径在Settings里找Project Interpreter点加号搜索就行。为什么要单独讲环境因为AI课程里十个学生有八个第一次跑命令行程序最容易反馈“我运行了但没反应”“颜色没出来”。提前把终端切到支持UTF-8这一步做好后面真正写逻辑时就能少打断课堂节奏。3.2 完整代码可以直接抄作业下面是我实际在用的版本注释我尽量留得清楚import sys import requests from datetime import datetime COLOR_MAP { red: \033[31m, green: \033[32m, yellow: \033[33m, blue: \033[34m, magenta: \033[35m, cyan: \033[36m, white: \033[37m, bold: \033[1m, reset: \033[0m } def color_print(text, colorwhite): if color in COLOR_MAP: start COLOR_MAP[color] end COLOR_MAP[reset] print(f{start}{text}{end}) else: print(text) WEATHER_CODE_MAP { 0: 晴, 1: 以晴为主, 2: 多云, 3: 阴, 45: 雾, 48: 冻雾, 51: 小毛毛雨, 53: 毛毛雨, 55: 大毛毛雨, 61: 小雨, 63: 中雨, 65: 大雨, 71: 小雪, 73: 中雪, 75: 大雪, 80: 小阵雨, 81: 阵雨, 82: 强阵雨, 95: 雷暴 } CITY_ALIAS { 北京: beijing, 上海: shanghai, 广州: guangzhou, 深圳: shenzhen } def get_coordinates(city_name): if city_name in CITY_ALIAS: city_name CITY_ALIAS[city_name] url https://geocoding-api.open-meteo.com/v1/search params {name: city_name, count: 1, language: zh, format: json} resp requests.get(url, paramsparams, timeout10) resp.raise_for_status() data resp.json() if not data.get(results): raise ValueError(f未找到城市{city_name}) item data[results][0] return item[latitude], item[longitude], item.get(name, city_name) def get_weather(lat, lon): url https://api.open-meteo.com/v1/forecast params { latitude: lat, longitude: lon, current: temperature_2m,relative_humidity_2m,weather_code,wind_speed_10m, timezone: Asia/Shanghai } resp requests.get(url, paramsparams, timeout10) resp.raise_for_status() return resp.json()[current] def weather_color(weather_code): if weather_code in (0, 1): return yellow if weather_code in (2, 3, 45, 48): return white if weather_code in (51, 53, 55, 61, 63, 65, 80, 81, 82, 95): return blue if weather_code in (71, 73, 75): return cyan return green def build_greeting(name, city, weather_info, weather_text): hour datetime.now().hour if hour 6: time_word 夜深了 elif hour 9: time_word 早上好 elif hour 12: time_word 上午好 elif hour 14: time_word 中午好 elif hour 18: time_word 下午好 else: time_word 晚上好 temp weather_info[temperature_2m] humidity weather_info[relative_humidity_2m] wind weather_info[wind_speed_10m] if temp 30: advice 热得够呛注意防暑补水 elif temp 20: advice 体感舒适适合出门走走 elif temp 10: advice 温度有点凉记得加件外套 elif temp 0: advice 比较冷注意保暖 else: advice 天寒地冻围巾手套安排上 return (f{time_word}{name}你在{city}当前天气{weather_text} f气温{temp}℃相对湿度{humidity}%风速{wind}km/h。{advice}。 f愿你今天心情也像天气一样清爽) def main(): if sys.platform.startswith(win): import colorama colorama.init() name input(请输入你的名字).strip() city input(请输入所在城市).strip() if not name: name 朋友 if not city: city 北京 try: lat, lon, city_std get_coordinates(city) weather_info get_weather(lat, lon) code weather_info[weather_code] weather_text WEATHER_CODE_MAP.get(code, 未知天气) color weather_color(code) msg build_greeting(name, city_std, weather_info, weather_text) color_print(msg, color) color_print( * 40, magenta) color_print(f数据来源Open-Meteo | 当前时间 {datetime.now().strftime(%Y-%m-%d %H:%M:%S)}, white) except requests.exceptions.RequestException as e: color_print(f网络请求失败{e}, red) except ValueError as e: color_print(f输入异常{e}, red) except Exception as e: color_print(f运行出错{e}, red) if __name__ __main__: main()说几个我测试过的细节。build_greeting里的f-string跨行拼接我用了括号包住这样代码不会超过80个字符阅读起来舒服。CITY_ALIAS里的兜底逻辑在上文讲过它解决的是中文名解析率不高的问题如果你想把代码精简掉也可以删掉这个字典直接全部传中文。3.3 运行效果与参数调整实际运行长这样我输入“林晓”和“上海”请输入你的名字林晓 请输入所在城市上海 下午好林晓你在上海当前天气小雨气温18℃相对湿度82%风速11km/h。温度有点凉记得加件外套。愿你今天心情也像天气一样清爽 数据来源Open-Meteo | 当前时间 2025-06-24 15:30:05第一行问候语的字体是蓝色的因为天气码对应了“小雨”系统自动选了blue。分割线是品红色信息行是白色。整体视觉效果一句话就是“终端的仪式感”。调整也很容易。想换颜色改COLOR_MAP里对应颜色的ANSI转义值就行比如红色\033[31m改成粉色你查一下对应代码填进去即可。想改文案风格直接动build_greeting里的字符串。想加“风力”判断把wind_speed_10m拿来做if判断再拼一段文案很顺手。4. 常见问题排查与避坑经验4.1 Windows终端中文乱码这个坑太常见了几乎每届学生都会踩。Windows默认控制台代码页经常是GBK我print出来带中文的字符串就会出现乱码。我自己跑教学班的时候最直接的办法是让同学在VSCode里运行把终端编码设为UTF-8或者打开CMD后先执行chcp 65001切到UTF-8代码页。Python3本身的源码是UTF-8编码问题主要出在控制台显示环节。如果你用的是命令行跑脚本chcp 65001是最省事的。要是还是乱码检查一下系统区域的“Beta版使用Unicode UTF-8提供全球语言支持”这个选项勾上重启绝大多数情况都好了。4.2 颜色不生效或出现大量转义字符如果你看到输出是一堆\033[31m这样的字符而不是颜色说明当前终端不支持ANSI转义序列。Windows老终端尤其是Cmd的旧版就是这样。解决方式就是让colorama.init()生效这个库在程序启动时把终端切到“支持ANSI”模式。加了之后还不行就换Windows Terminal新终端默认支持。还有一种情况是你在IDE的Output面板里运行有些IDE的日志窗口不解析ANSI。这种情况下颜色输出不了但也不会出现乱码的转义字符属于预期行为。教学时我会提醒学生想要最佳效果请在真正的终端里运行比如VSCode的集成终端。4.3 找不到城市或解析到错误城市刚才代码里抛了ValueError(未找到城市)这是兜底。但更气人的是解析到错误城市比如你输入“中山”结果匹配到别的国家的中山。Open-Meteo的geocoding接口有一个参数countryCode你可以限定国家比如中国是CN能减少误匹配。我不建议新手加太多参数但可以在课程扩展环节提一下。最稳妥的方案是你在代码里维护一个小字典把你需要的城市写成“中文名-经纬度”的键值对。虽说写死了不够优雅但在演示场景里是最稳定、最不依赖外部服务的做法。4.4 请求超时和免费接口的限制Open-Meteo虽然是免费接口但也不是无限量给你刷的。如果你连续高频请求服务会拒绝你。我在代码里给每个请求都加timeout10就是避免某个请求卡死时整个程序挂着不动。这个方法虽然简单但能救场。如果哪天接口真的不可用了代码里的异常捕获会把“网络请求失败”打出来学生至少知道不是自己语法写错了。至于要不要换备用接口课程场景下我一般不展开重点是把“外部服务可能挂程序要想好退路”这个意识传递到位。4.5 常见问题速查表现象可能原因解决办法中文输出乱码控制台代码页不对CMD执行chcp 65001或VSCode终端用UTF-8颜色没出来终端不支持ANSI加colorama.init()换Windows Terminal出现\033转义字符同上同上城市找不到中文名解析失败改用CITY_ALIAS拼音兜底或维护经纬度字典程序卡住不动网络请求无响应检查网络代码里加timeout参数天气数据是“未知天气”新天气码没映射打印weather_code对照WMO表补进字典5. 从这个小工具到AI课程的思维跃迁5.1 可以往哪些方向扩展这个小程序完全具备“长成大树”的潜质。我给课程设计的扩展路径有几条你可以按学生的兴趣挑第一命令行参数化。把input()改成用argparse接收命令行参数运行方式变成python weather.py 林晓 上海听起来就专业不少。第二多城市对比。把城市列表传进去循环输出好几个城市的天气卡片用分隔线隔开很有仪表盘的感觉。第三写入Excel。把每天的数据追加到openpyxl工作表里累积一周就能画气温折线图这就自然衔接到了数据分析。更贴近AI课程主题的扩展是让大模型来生成问候语。你可以保留“获取天气”这个后端逻辑把天气数据拼成一段Prompt丢给大模型生成更自然、更有梗的问候文案。学生看到“AI生成”和“规则生成”两种效果对比对这个项目的理解会立刻上一个层次。5.2 教学场景中的使用建议作为AI课程的教练项目我建议分“三步走”来带学生。第一步先让他们把程序原样跑起来什么都别改体验完整的“输入-处理-输出”流程。第二步让他们改颜色和问候语这能加深对字典、字符串拼接和函数返回值的理解。第三步再引入一个没有被映射的天气码让学生自己查WMO表、加进字典这一步考验的是“看懂代码以后动手改”的能力。课时紧张的话第二步和第三步可以合并让每个学生做一个“只属于自己版本”的问候程序分享到群里互相看看效果。这种即时反馈带来的成就感比任何测试数据都能说明问题。最后分享一个我自己的小体会这类综合小项目最重要的价值不在于代码量有多大而在于它把一个真实场景的完整链路压缩到了新手能消化的范围内。学生在它身上练熟的不只是语法还有“拆解需求、调用服务、处理异常、迭代优化”这套做事的思维。我的建议是把这个程序反复改三遍以上。第一遍跑通第二遍加功能第三遍精简代码。三次下来Python基础基本就活了。
返回列表