-1

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:\Users\Hania\Desktop\ppp\WeatherApp.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.

asked Aug 7, 2024 at 12:12
5
  • What is the value you tested for city? What is the response you get? print(response) Commented Aug 7, 2024 at 13:06
  • As soon as I run the code, it gives that error which I sharded in my question, before me writing any city name in the search box Commented Aug 7, 2024 at 13:17
  • You are probably getting Error 400 as aresponse as lat and lon are required parameters, which you are not sending openweathermap.org/api/one-call-3 Commented Aug 7, 2024 at 13:26
  • I know that but all the videos and websites I visited, they are doing the same thing like me and don't get any error. Also, do you have knowledge of any other free weather api for Python gui??? Commented Aug 7, 2024 at 13:37
  • The API is perfectly fine. The problem is unfortunately your code. You have to move the codeblock where you are calling the API inside a function, otherwise it's called instantly when you run the script. Check my answer for a minimal example you can adapt. Commented Aug 7, 2024 at 14:16

2 Answers 2

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()
answered Aug 7, 2024 at 13:48
Sign up to request clarification or add additional context in comments.

2 Comments

I have already tried this code out, but unfortunately, it did not work. By the way thanks for your help!
What is the problem you are facing?
1

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

answered Aug 8, 2024 at 19:35

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.