Skip to content
Advertisement

Tkinter App – TypeError: can only concatenate str (not “StringVar”) to str

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.

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement