Search code examples
pythonapitkinteropenweathermap

Unable to retrieve temperature using openweathermap API in tkinter


I am trying to retrieve the temperature of a city using the openweathermap api however I am not able to retrieve it. I am able to retrieve the City name but not temperature and other bits I would like to retrieve. I know its probably to do with how I am trying to retrieve it but I can't figure it out.

Here is my code for trying to get the name and temperature (name works but temperature does not)

def format_response(weather):
    try:
        name = weather['city']['name']
        temperature = weather['main']['temp']
        final_str = f'City: {name} \n Temperature {temperature}'
    except:
        final_str = 'There was a problem retrieving that information'

    return final_str

And here is the JSON given for expected API response on the openweathermap website which matches the output in my console.

{
  "cod": "200",
  "message": 0,
  "cnt": 40,
  "list": [
    {
      "dt": 1647345600,
      "main": {
        "temp": 286.88,
        "feels_like": 285.93,
        "temp_min": 286.74,
        "temp_max": 286.88,
        "pressure": 1021,
        "sea_level": 1021,
        "grnd_level": 1018,
        "humidity": 62,
        "temp_kf": 0.14
      },
      "weather": [
        {
          "id": 804,
          "main": "Clouds",
          "description": "overcast clouds",
          "icon": "04d"
        }
      ],
      "clouds": {
        "all": 85
      },
      "wind": {
        "speed": 3.25,
        "deg": 134,
        "gust": 4.45
      },
      "visibility": 10000,
      "pop": 0,
      "sys": {
        "pod": "d"
      },
      "dt_txt": "2022-03-15 12:00:00"
    },
    {
      "dt": 1647356400,
      "main": {
        "temp": 286.71,
        "feels_like": 285.77,
        "temp_min": 286.38,
        "temp_max": 286.71,
        "pressure": 1021,
        "sea_level": 1021,
        "grnd_level": 1017,
        "humidity": 63,
        "temp_kf": 0.33
      },
      "weather": [
        {
          "id": 804,
          "main": "Clouds",
          "description": "overcast clouds",
          "icon": "04d"
        }
      ],
      "clouds": {
        "all": 90
      },
      "wind": {
        "speed": 3.34,
        "deg": 172,
        "gust": 4.03
      },
      "visibility": 10000,
      "pop": 0,
      "sys": {
        "pod": "d"
      },
      "dt_txt": "2022-03-15 15:00:00"
    },

    ...

 ],
  "city": {
    "id": 2643743,
    "name": "London",
    "coord": {
      "lat": 51.5073,
      "lon": -0.1277
    },
    "country": "GB",
    "population": 1000000,
    "timezone": 0,
    "sunrise": 1647324903,
    "sunset": 1647367441
  }
}

Solution

  • Given the JSON you've provided, you need to loop over the "list" property and then access the ["main"]["temp"] field of each item:

    def get_temps(weather_data):
        for e in weather_data["list"]:
            print(e["main"]["temp"])
    
    # this is your JSON clipped to 2 items in the 
    # 'list' property
    js = {
      "cod": "200",
      "message": 0,
      "cnt": 40,
      "list": [
        {
          "dt": 1647345600,
          "main": {
            "temp": 286.88,
            "feels_like": 285.93,
            "temp_min": 286.74,
            "temp_max": 286.88,
            "pressure": 1021,
            "sea_level": 1021,
            "grnd_level": 1018,
            "humidity": 62,
            "temp_kf": 0.14
          },
          "weather": [
            {
              "id": 804,
              "main": "Clouds",
              "description": "overcast clouds",
              "icon": "04d"
            }
          ],
          "clouds": {
            "all": 85
          },
          "wind": {
            "speed": 3.25,
            "deg": 134,
            "gust": 4.45
          },
          "visibility": 10000,
          "pop": 0,
          "sys": {
            "pod": "d"
          },
          "dt_txt": "2022-03-15 12:00:00"
        },
        {
          "dt": 1647356400,
          "main": {
            "temp": 286.71,
            "feels_like": 285.77,
            "temp_min": 286.38,
            "temp_max": 286.71,
            "pressure": 1021,
            "sea_level": 1021,
            "grnd_level": 1017,
            "humidity": 63,
            "temp_kf": 0.33
          },
          "weather": [
            {
              "id": 804,
              "main": "Clouds",
              "description": "overcast clouds",
              "icon": "04d"
            }
          ],
          "clouds": {
            "all": 90
          },
          "wind": {
            "speed": 3.34,
            "deg": 172,
            "gust": 4.03
          },
          "visibility": 10000,
          "pop": 0,
          "sys": {
            "pod": "d"
          },
          "dt_txt": "2022-03-15 15:00:00"
        }
     ],
      "city": {
        "id": 2643743,
        "name": "London",
        "coord": {
          "lat": 51.5073,
          "lon": -0.1277
        },
        "country": "GB",
        "population": 1000000,
        "timezone": 0,
        "sunrise": 1647324903,
        "sunset": 1647367441
      }
    }
    
    get_temps(js)
    

    And I get this:

    286.88
    286.71
    

    If you only care about, say, getting the most recent temperature reading, you can just read the first item of the list.

    # I don't know if this API can return an empty list, but
    # this also makes sure you don't access an empty list
    def get_latest_temp(weather_data):
        if weather_data["list"]:
            return weather_data["list"][0]["main"]["temp"]
        else:
            return None