I am trying to build a weather app in tkinter for class and I am stuck! I keep getting the following error message in the console:
PS C:UserssmhalDesktopWeatherApp> & C:/Users/smhal/AppData/Local/Programs/Python/Python310/python.exe c:/Users/smhal/Desktop/WeatherApp/WeatherApp.py Exception in Tkinter callback Traceback (most recent call last): File "C:UserssmhalAppDataLocalProgramsPythonPython310libtkinter__init__.py",line 1921, in __call__ return self.func(*args) File "c:UserssmhalDesktopWeatherAppWeatherApp.py", line 26, in getWeather "url = 'https://api.openweathermap.org/data/2.5/weather?zip=' + zip + 'us&appid='+api_key TypeError: can only concatenate str (not "StringVar") to str
Error Message from Visual Studio Code
Here’s my Python code:
from tkinter import * from urllib import response import requests import json from datetime import datetime #Initialize Window root = Tk() root.geometry("400x400") root.resizable(False, False) root.title("CMSC 492 - Weather Widget App") def time_format_for_location(utc_with_tz): local_time = datetime.utcfromtimestamp(utc_with_tz) return local_time.time() zip = StringVar() def getWeather(): api_key = '2308a72d96e697b096597a3d4589d9ff' #zip input from user zip_input = zip.get() #openweater url url = 'https://api.openweathermap.org/data/2.5/weather?zip=' + zip + 'us&appid=' + api_key #get url response response = requests.get(url) #make json python readable weather_data = response.json() tfield.delete("1.0", "end") if weather_data['cod'] == 200: kelvin = 273 #store fetched values temp = int(weather_data['main']['temp'] - kelvin) feels_like = int(weather_data['main']['feels_like'] - kelvin) pressure = weather_data['main']['pressure'] humidity = weather_data['main']['humidity'] wind_speed = weather_data['wind']['speed'] * 3.6 sunrise = weather_data['sys']['sunrise'] sunset = weather_data['sys']['sunset'] timezone = weather_data['timezone'] cloudy = weather_data['clouds']['all'] description = weather_data['weather'][0]['description'] sunrise_time = time_format_for_location(sunrise + timezone) sunrise_time = time_format_for_location(sunset + timezone) #assign values to display weather = f"nWeather in: {zip_input}nTemperature: {temp}°nFeels Like: {feels_like}°" else: weather = f"ntWeather for '{zip_input}' not found" tfield.insert(INSERT, weather) zip_head = Label(root, text = 'Enter Zip Code', font='Arial 10 bold').pack(pady=10) zip_input = Entry(root, textvariable=zip, width=24, font='Arial 14 bold').pack() Button(root, command=getWeather, text='Check Weather', font='arial 10', bg='lightblue', fg='black', activebackground='teal', padx=5, pady=5).pack(pady=20) weather_now = Label(root, text='Current Weather: ', font='arial 12 bold').pack(pady=10) tfield = Text(root, width=46, height=10) tfield.pack() root.mainloop()
So, the API I used is supposed to accept the zip code which is what I am collecting using:
zip_input = Entry(root, textvariable=zip, width=24, font='Arial 14 bold').pack()
I’m not sure how else I can collect the zip than with StringVar()
Any help/guidance would be extremely appreciated.
Advertisement
Answer
I suppose the content of zip
should contain user input as integer. You can convert it to string using str()
:
url = 'https://api.openweathermap.org/data/2.5/weather?zip=' + str(zip) + 'us&appid=' + api_key
Consider using a variable, e.g. zip_str
, instead of calling str()
multiple times.
You also might want to validate the user input.