skip to Main Content

I’m making a Python gui project using Tkinter module. The main problem is that I’ve searched multiple times, but can’t find a website for a free api. Many websites are saying to use OpenWeatherMap api but it is not working for me.
My code was :

from tkinter import *
import tkinter as tk
from geopy.geocoders import Nominatim
from tkinter import ttk, messagebox
from timezonefinder import TimezoneFinder
from datetime import datetime
import requests
import pytz
import json


root = Tk()
root.title("Weather")
root.geometry("900x500+300+200")
root.config(bg = "lightgrey")
root.resizable(True, False)

# search box
Search_image = PhotoImage(file = "Copy of search.png")
myimage = Label(image = Search_image)
myimage.place(x = 20, y = 20) 

def getWeather():
    city = textfield.get()
    geolocator = Nominatim(user_agent = "geopiExercises")
    location = geolocator.geocode(city)
    obj = TimezoneFinder()
    result = obj.timezone_at(lng = location.longitude, lat =      location.latitude)
    home = pytz.timezone(result)
    local_time = datetime.now(home)
    current_time = local_time.strftime("%I:%M:%p")
    print(current_time)
    clock.config(text = current_time)
    name.config(text = "CURRENT TIME")

textfield = tk.Entry(root, justify = "center", width =  22,font = ("poppins",25,"bold" ), bg = "#404040", border = 0, fg = "white") 
textfield.place(x = 54, y = 40)
textfield.focus()


city = textfield.get()
api_key = "my api key"
api = "https://api.openweathermap.org/data/3.0/onecall?" +      city + "&appid=my api key"
json_data = requests.get(api)
response = json_data.json()
condition = response['weather'][0]['main']
description = response['weather'][0]['description']
temp = int(response['main']['temp']-273.15)
pressure = response['main']['pressure']
humidity = response['main']['humidity']
wind = response['wind']['speed']

print(response)

textfield.delete(1.0, END)



Search_icon = PhotoImage(file = "Copy of search_icon.png")
myimage2 = Button(image = Search_icon,borderwidth = 0,cursor = "hand2", bg = "#404040", command = getWeather )
myimage2.place(x = 380, y = 33)


#logo
Logo_image = PhotoImage(file = "logo.png")
myimage3 = Label(image = Logo_image)
myimage3.place(x = 150, y = 100)


# Bottom box
Frame_image = PhotoImage(file = "Copy of box.png")
myimage4 = Label(image = Frame_image)
myimage4.pack(padx = 5, pady = 5, side = BOTTOM)

# time
name = Label(root, font = ("arial",15 , "bold"))
name.place(x = 30, y = 100)
clock = Label(root, font = ("Helvetica", 20,"bold"))
clock.place(x = 30, y = 120)
# Label
label1 = Label(root, text = "WIND", font = ("Helvetica",15,"bold"), fg = "white", bg = "#1ab5ef")
label1.place(x = "120", y = "400")

label2 = Label(root, text = "HUMIDITY", font =  ("Helvetica",15,"bold"), fg = "white", bg = "#1ab5ef")
label2.place(x = "250", y = "400")

label3 = Label(root, text = "CONDITION", font = ("Helvetica",15,"bold"), fg = "white", bg = "#1ab5ef")
label3.place(x = "430", y = "400")

label4 = Label(root, text = "PRESSURE", font = ("Helvetica",15,"bold"), fg = "white", bg = "#1ab5ef")
label4.place(x = "650", y = "400")

t = Label(font = ("arial", 70, "bold"), fg = "#ee666d")
t.place(x = 400, y = 150 )
c = Label(font = ("arial", 15, "bold"))
c.place(x = 400, y = 250 )
t.config(text = (temp, "°"))
c.config(text = (condition, "|", "FEELS", "LIKE", temp, "°"))

w = Label(text = "...", font = ("arial", 20, "bold"), bg = "#1ab5ef")
w.place(x = 130 , y = 430)

w2 = Label(text = "...", font = ("arial", 20, "bold"), bg = "#1ab5ef")
w2.place(x = 280 , y = 430)

w3 = Label(text = "...", font = ("arial", 20, "bold"), bg = "#1ab5ef")
w3.place(x = 450 , y = 430)

w4 = Label(text = "...", font = ("arial", 20, "bold"), bg = "#1ab5ef")
w4.place(x = 670 , y = 430)
root.mainloop()

The error I get after executing the above code is:

Traceback (most recent call last):
  File "C:UsersHaniaDesktoppppWeatherApp.py", line 53,  in <module>
    condition = response['weather'][0]['main']
KeyError: 'weather'

I think that the code is perfectly fine and the error is related to the api. Please suggest what to do.
Thanks in advance.

2

Answers


  1. The problem with your code is that the api is requested before you enter a value for the text field. As lat and lon are required parameter for the OpenWeather API, you get Error 400 as a response (see here)

    Try this minimal example of what you are trying to achieve

    import tkinter as tk
    import requests
    import json
    
    api_key = 'YOUR_API_KEY'
    
    
    def get_weather():
        city = user_input.get()
        url = f'http://api.openweathermap.org/data/2.5/weather?q={city}&appid={api_key}'
        response = requests.get(url)
    
        if response.status_code == 200:
            data = response.json()
            temp = data['main']['temp']
            desc = data['weather'][0]['description']
            print(f'Temperature: {temp} K')
            print(f'Description: {desc}')
        else:
            print('Error fetching weather data')
    
    root = tk.Tk()
    
    user_input = tk.StringVar(root)
    
    entry = tk.Entry(root, textvariable=user_input)
    entry.pack()
    
    trigger_search = tk.Button(root, text='Get weather', command=get_weather)
    trigger_search.pack()
    
    root.mainloop()
    
    Login or Signup to reply.
  2. Many websites are saying to use OpenWeatherMap api but it is not
    working for me

    In your script. You had like this:

    enter image description here

    Your place() isn’t appropriately laid out.

    You had too many Tkinter widgets. So you can reduce the number of widgets. It is up to you.

    Don’t use this https://api.openweathermap.org/data/3.0/onecall? It asking for:

    {‘cod’: 401, ‘message’: ‘Please note that using One Call 3.0 requires
    a separate subscription to the One Call by Call plan. Learn more here
    https://openweathermap.org/price. If you have a valid subscription to
    the One Call by Call plan, but still receive this error, then please
    see https://openweathermap.org/faq#error401 for more info.’}

    Notice. you cannot run on fly like this without create function:

    condition = response['weather'][0]['main']
    description = response['weather'][0]['description']
    temp = int(response['main']['temp']-273.15)
    pressure = response['main']['pressure']
    humidity = response['main']['humidity']
    wind = response['wind']['speed']
    
    print(response)
    

    It doesn’t do work.

    So Here is the code:

    import tkinter as tk
    from geopy.geocoders import Nominatim
    from tkinter import ttk, messagebox
    from timezonefinder import TimezoneFinder
    from datetime import datetime
    import requests
    import pytz
     
    
    
    root = tk.Tk()
    root.title("Weather")
    root.geometry("900x500+300+200")
    root.config(bg = "lightgrey")
    #root.resizable(True, False)
    
    # search box
    Search_image = tk.PhotoImage(file = "p2.png")
    myimage = tk.Label(root, image = Search_image)
    myimage.place(x = 20, y = 20)
    
        
    def getWeather():
        city = str(textfield.get())
        print(city)
        geolocator = Nominatim(user_agent = "geopiExercises")
        location = geolocator.geocode(str(city))
        print((location.latitude, location.longitude))
        obj = TimezoneFinder()
         
        result = obj.timezone_at(lat=location.latitude, lng=location.longitude)
        print(result)
        home = pytz.timezone(result)
        local_time = datetime.now()
        current_time = local_time.strftime("%I:%M:%p")
        print(current_time)
        clock.config(text = current_time)
        name.config(text = "CURRENT TIME")
        data = f' CURRENT TIME n{current_time}'
         
    
        
    def format_response(weather):
        getWeather()
        
        try:
            name = weather['city']['name']
            temperature_today = weather['list'][0]['main']['temp']
            desc = weather['list'][0]['weather'][0]['description']
            temp_feels = weather['list'][0]['main']['feels_like']
            humidity = weather['list'][0]['main']['humidity']
            wind_speed = weather['list'][0]['wind']['speed']
    
            final_str = f'City: {name} nTemperature now: {temperature_today}°C --- feels like: {temp_feels}°C nCondtions: {desc} nHumidty: {humidity}% nWind Speed: {wind_speed}m/s'
    
        except:
            final_str = 'There was a problem retrieving that information'
    
        return final_str
        
    
         
    def get_weather(city):    
        city = textfield.get()
        api_key = "a9f553857df50650433c1577e3be6538"
        url = 'http://api.openweathermap.org/data/2.5/forecast'  
        params = {'q': city, 'appid': api_key, 'units': 'metric'}
        response = requests.get(url, params=params)
        weather = response.json()
        t['text'] = format_response(weather)
         
    
    #condition = response['weather'][0]['main']
    #description = response['weather'][0]['description']
    #temp = int(response['main']['temp']-273.15)
    #pressure = response['main']['pressure']
    #humidity = response['main']['humidity']
    #wind = response['wind']['speed']
    
     
    
    #textfield.delete(1.0, tk.END)
    
    textfield = tk.Entry(root, justify = "center", width =22,font = ("poppins",25,"bold" ), bg = "#404040", border = 0, fg = "white") 
    textfield.place(x = 330, y = 40)
    textfield.focus()
    
    Search_icon = tk.PhotoImage(file = "p1.png")
    myimage2 = tk.Button(root, image = Search_icon,borderwidth = 0,cursor = "hand2",
                         bg = "yellow", command =lambda: get_weather(textfield.get()))
    myimage2.place(x = 20, y = 240)
    
    
    #logo
    Logo_image = tk.PhotoImage(file = "p9.png")
    myimage3 = tk.Label(image = Logo_image)
    myimage3.place(x = 320, y = 380)
     
    
    # Bottom box
    Frame_image = tk.PhotoImage(file = "p3.png")
    myimage4 = tk.Label(root, bg='aqua', image = Frame_image)
    myimage4.place(x = 480, y = 380)
    
    # time
    name = tk.Label(root, width=20, bg= 'orange', font = ("arial",15 , "bold"))
    name.place(x = 330, y = 100)
    
    clock = tk.Label(root, bg='blue', fg='white', width=20, font = ("Helvetica", 15,"bold"))
    clock.place(x = 580, y = 100)
    # Label
    #label1 = tk.Label(root, text = "WIND", font = ("Helvetica",15,"bold"), fg = "white", bg = "#1ab5ef")
    #label1.place(x = "120", y = "400")
    
    #label2 = tk.Label(root, text = "HUMIDITY", font =  ("Helvetica",15,"bold"), fg = "white", bg = "#1ab5ef")
    #label2.place(x = "250", y = "400")
    
    #label3 = tk.Label(root, text = "CONDITION", font = ("Helvetica",15,"bold"), fg = "white", bg = "#1ab5ef")
    #label3.place(x = "430", y = "400")
    
    #label4 = tk.Label(root, text = "PRESSURE", font = ("Helvetica",15,"bold"), fg = "white", bg = "#1ab5ef")
    #label4.place(x = "650", y = "400")
    
    t = tk.Label(root, bg='aqua',  font = ("arial", 15, "bold"), width=50, fg = "black", anchor="w", justify=tk.LEFT)
    t.place(x = 330, y = 150 )
    c = tk.Label(root, width=20, fg='white', bg='black', font = ("arial", 15, "bold"))
    #c.place(x = 400, y = 265 )
    #t.config(text ='temp')
    #c.config(text =  "FEELS LIKE" )
    
    #w = tk.Label(text = "...", font = ("arial", 20, "bold"), bg = "#1ab5ef")
    #w.place(x = 130 , y = 430)
    
    #w2 = tk.Label(text = "...", font = ("arial", 20, "bold"), bg = "#1ab5ef")
    #w2.place(x = 280 , y = 430)
    
    #w3 = tk.Label(text = "...", font = ("arial", 20, "bold"), bg = "#1ab5ef")
    #w3.place(x = 450 , y = 430)
    
    #w4 = tk.Label(text = "...", font = ("arial", 20, "bold"), bg = "#1ab5ef")
    #w4.place(x =70 , y = 30)
    root.mainloop()
    

    Screenshot:

    enter image description here

    Btw, if you want to all widgets, Then comment out.

    It will look like this:

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search