Python Tkinter天气应用JSON多字典遍历及forecast函数问题求解
问题修复方案
问题1:多匹配城市无法全部展示修复
- 原逻辑缺陷:固定遍历0-9的索引会在接口返回数据不足10条时报索引越界错误,且所有按钮都放在同一行导致后生成的按钮覆盖之前的内容
- 修复逻辑:直接遍历接口返回的城市列表,为每个城市动态分配行号生成按钮,同时新增旧按钮清空逻辑,避免多次查询产生冗余控件
问题2:forecast函数作用域与参数传递报错修复
- 原逻辑缺陷:forecast函数定义在citylookup的异常捕获分支内,正常流程无法访问;id_key属于城市查询的临时变量,全局函数无法直接读取
- 修复逻辑:将forecast移到全局作用域,定义为接收城市id作为入参的通用函数,绑定按钮命令时用lambda闭包传入对应城市的id值,避免变量覆盖
额外修复的隐藏问题
- 自动补全接口请求URL拼接错误,原代码apikey参数后缺少
&q=参数前缀,导致请求始终失败 - id_key是普通字符串,原代码错误调用
.get()方法取值 - 接口返回的温度、湿度等字段为数值类型,需转字符串后才能拼接进文本
- 天气预报接口返回结构读取错误,原代码直接用
api2[0]读取数据不符合AccuWeather的返回结构
修复后完整代码
from tkinter import * import requests import json root = Tk() root.title("天气查询应用") root.geometry("550x400") root.configure(background="green") # 天气预报函数移到全局作用域,接收城市key作为参数 def forecast(city_key): try: api_request2 = requests.get("http://dataservice.accuweather.com/forecasts/v1/daily/1day/" + city_key + "?apikey=替换为你自己的AccuWeather密钥&language=fr-FR&details=true&metric=true") api2 = json.loads(api_request2.content) # 按接口实际结构提取字段并转字符串 temperature = str(api2["DailyForecasts"][0]["Temperature"]["Maximum"]["Value"]) humidite = str(api2["DailyForecasts"][0]["Day"]["RelativeHumidity"]["Average"]) uvindex = str(api2["DailyForecasts"][0]["AirAndPollen"][0]["Value"]) precipitation = str(api2["DailyForecasts"][0]["Day"]["PrecipitationProbability"]) mylabel = Label(root,text=f"今日天气:\n最高温度:{temperature}℃\n相对湿度:{humidite}%\nUV指数:{uvindex}\n降水概率:{precipitation}%") mylabel.grid(row=10, column=0, columnspan=2) except Exception as e: error_label = Label(root, text="天气数据查询失败") error_label.grid(row=10, column=0, columnspan=2) def citylookup(): # 清空之前生成的城市按钮和天气信息 for widget in root.winfo_children(): row_num = int(widget.grid_info()["row"]) if row_num > 0: widget.destroy() try: # 修复URL拼接错误,添加&q=参数 api_request = requests.get( "http://dataservice.accuweather.com/locations/v1/cities/autocomplete?apikey=" "替换为你自己的AccuWeather密钥&q=" + city_search.get() + "&language=fr-FR") api = json.loads(api_request2.content) # 遍历所有返回的城市,动态分配行号 for index, city in enumerate(api): localisation = city["LocalizedName"] region_adm = city["AdministrativeArea"]["ID"] id_key = city["Key"] # 用lambda闭包传递当前城市的id_key button = Button(root, text=localisation + ", " + region_adm, command=lambda k=id_key: forecast(k)) button.grid(row=index+1, column=0, columnspan=2, sticky=W+E) except Exception as e: error_label = Label(root, text="城市查询失败,请检查输入或密钥") error_label.grid(row=1, column=0, columnspan=2) city_search = Entry(root) city_search.grid(row=0, column=0, stick=W+E+N+S) city_button = Button(root, text="查询城市", command=citylookup) city_button.grid(row=0, column=1, stick=W+E+N+S) root.mainloop()
内容的提问来源于stack exchange,提问作者Mélissa Ch.
相关产品推荐
相关产品推荐

