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.
2 Answers 2
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()
2 Comments
Many websites are saying to use OpenWeatherMap api but it is not working for me
In your script. You had like this:
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:
Btw, if you want to all widgets, Then comment out.
It will look like this:
Comments
Explore related questions
See similar questions with these tags.
city? What is the response you get?print(response)Error 400as aresponse aslatandlonare required parameters, which you are not sending openweathermap.org/api/one-call-3