You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.16 10:36:01