使用Python+Tkinter开发天气查询界面遇KeyError: 'main'问题求助
KeyError: 'main' 错误分析与修复方案
问题重现
尝试用Python+Tkinter开发城市气温查询界面时,运行到temp_kelvin=weatherinfo['main']['temp']行出现KeyError: 'main'报错,原代码如下:
from tkinter import * import requests root=Tk() root.title("WEATHER API") root.geometry("400x400") city=StringVar() def getweather(): CITY=city.get() api_id="abb8cea2239face8fbb7401add34d73e" URL="https://api.openweathermap.org/data/2.5/weather?"+CITY+"appid="+api_id response=requests.get(URL) weatherinfo = response.json() if weatherinfo['cod']!='404': temp_kelvin=weatherinfo['main']['temp'] temp_celsius=temp_kelvin-273 temp_farhenheit=temp_celsius *(9/5) + 32 Labelc=Label(temp_celsius) Labelf=Label(temp_farhenheit) Labelc.pack() Labelf.pack() else: error=Label(text="ERROR") error.pack() city=Entry(root) city.pack() Mybutton=Button(root,text="CHECK STATS",command=getweather).pack() root.mainloop()
错误原因
API请求URL格式错误:
OpenWeatherMap的API要求城市参数必须用q=指定,且参数之间需用&分隔。原URL拼接后变成https://api.openweathermap.org/data/2.5/weather?城市名appid=密钥,属于无效请求,返回的JSON数据中没有main字段,直接访问就会触发KeyError。变量名冲突:
先定义city=StringVar(),之后又重新赋值city=Entry(root),导致getweather函数中调用的city.get()实际是Entry组件的方法,虽能获取输入内容,但写法混淆,且未将输入框与StringVar绑定,不符合Tkinter规范。Label组件创建错误:
创建Label必须指定父容器(如root),且text参数需传入字符串。原代码中Label(temp_celsius)把温度数值当作父组件,会导致组件创建失败,无法正常显示温度。
修复方案
步骤1:修正API请求URL
用f-string拼接正确格式的URL,添加q=参数和&分隔符:
URL = f"https://api.openweathermap.org/data/2.5/weather?q={CITY}&appid={api_id}"
步骤2:解决变量名冲突并绑定StringVar
将StringVar变量名改为city_var,并绑定到Entry组件:
city_var = StringVar() # ... city_entry = Entry(root, textvariable=city_var) city_entry.pack() # 在getweather函数中获取值: CITY = city_var.get()
步骤3:修正Label组件创建
创建Label时指定父容器和格式化后的温度文本:
c_label = Label(root, text=f"摄氏温度: {temp_celsius:.2f}°C") f_label = Label(root, text=f"华氏温度: {temp_farhenheit:.2f}°F")
步骤4:完善错误处理
添加空输入检查、HTTP请求异常捕获,同时处理API返回cod为整数的情况。
完整修复代码
from tkinter import * import requests root = Tk() root.title("WEATHER API") root.geometry("400x400") # 定义StringVar并绑定到输入框 city_var = StringVar() def getweather(): CITY = city_var.get() if not CITY: error = Label(root, text="请输入城市名") error.pack() return api_id = "abb8cea2239face8fbb7401add34d73e" # 修正URL格式 URL = f"https://api.openweathermap.org/data/2.5/weather?q={CITY}&appid={api_id}" try: response = requests.get(URL) response.raise_for_status() # 捕获HTTP请求错误 weatherinfo = response.json() # API返回的cod可能是整数 if weatherinfo.get('cod') != 404: # 先检查main字段是否存在 if 'main' in weatherinfo: temp_kelvin = weatherinfo['main']['temp'] temp_celsius = temp_kelvin - 273.15 # 更精确的转换 temp_farhenheit = temp_celsius * (9/5) + 32 # 正确创建Label组件 temp_title = Label(root, text="当前温度:") temp_title.pack() c_label = Label(root, text=f"摄氏: {temp_celsius:.2f}°C") c_label.pack() f_label = Label(root, text=f"华氏: {temp_farhenheit:.2f}°F") f_label.pack() else: error = Label(root, text="无法获取温度数据") error.pack() else: error = Label(root, text="城市不存在,请检查输入") error.pack() except requests.exceptions.RequestException as e: error = Label(root, text=f"请求出错: {str(e)}") error.pack() # 创建输入框并绑定StringVar city_entry = Entry(root, textvariable=city_var) city_entry.pack() # 创建按钮 check_btn = Button(root, text="CHECK STATS", command=getweather) check_btn.pack() root.mainloop()
内容的提问来源于stack exchange,提问作者ArnavK
相关产品推荐
相关产品推荐

