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:
JavaScript
x
11
11
1
PS C:UserssmhalDesktopWeatherApp> &
2
C:/Users/smhal/AppData/Local/Programs/Python/Python310/python.exe
3
c:/Users/smhal/Desktop/WeatherApp/WeatherApp.py
4
Exception in Tkinter callback
5
Traceback (most recent call last):
6
File "C:UserssmhalAppDataLocalProgramsPythonPython310libtkinter__init__.py",line 1921, in __call__
7
return self.func(*args)
8
File "c:UserssmhalDesktopWeatherAppWeatherApp.py", line 26, in getWeather
9
"url = 'https://api.openweathermap.org/data/2.5/weather?zip=' + zip + 'us&appid='+api_key
10
TypeError: can only concatenate str (not "StringVar") to str
11
Error Message from Visual Studio Code
Here’s my Python code:
JavaScript
1
71
71
1
from tkinter import *
2
from urllib import response
3
import requests
4
import json
5
from datetime import datetime
6
7
#Initialize Window
8
root = Tk()
9
root.geometry("400x400")
10
root.resizable(False, False)
11
root.title("CMSC 492 - Weather Widget App")
12
13
def time_format_for_location(utc_with_tz):
14
local_time = datetime.utcfromtimestamp(utc_with_tz)
15
return local_time.time()
16
17
zip = StringVar()
18
19
def getWeather():
20
api_key = '2308a72d96e697b096597a3d4589d9ff'
21
22
#zip input from user
23
zip_input = zip.get()
24
25
#openweater url
26
url = 'https://api.openweathermap.org/data/2.5/weather?zip=' + zip + 'us&appid=' + api_key
27
28
#get url response
29
response = requests.get(url)
30
31
#make json python readable
32
weather_data = response.json()
33
34
tfield.delete("1.0", "end")
35
36
if weather_data['cod'] == 200:
37
kelvin = 273
38
39
#store fetched values
40
temp = int(weather_data['main']['temp'] - kelvin)
41
feels_like = int(weather_data['main']['feels_like'] - kelvin)
42
pressure = weather_data['main']['pressure']
43
humidity = weather_data['main']['humidity']
44
wind_speed = weather_data['wind']['speed'] * 3.6
45
sunrise = weather_data['sys']['sunrise']
46
sunset = weather_data['sys']['sunset']
47
timezone = weather_data['timezone']
48
cloudy = weather_data['clouds']['all']
49
description = weather_data['weather'][0]['description']
50
51
sunrise_time = time_format_for_location(sunrise + timezone)
52
sunrise_time = time_format_for_location(sunset + timezone)
53
54
#assign values to display
55
weather = f"nWeather in: {zip_input}nTemperature: {temp}°nFeels Like: {feels_like}°"
56
else:
57
weather = f"ntWeather for '{zip_input}' not found"
58
59
tfield.insert(INSERT, weather)
60
61
zip_head = Label(root, text = 'Enter Zip Code', font='Arial 10 bold').pack(pady=10)
62
zip_input = Entry(root, textvariable=zip, width=24, font='Arial 14 bold').pack()
63
64
Button(root, command=getWeather, text='Check Weather', font='arial 10', bg='lightblue', fg='black', activebackground='teal', padx=5, pady=5).pack(pady=20)
65
66
weather_now = Label(root, text='Current Weather: ', font='arial 12 bold').pack(pady=10)
67
tfield = Text(root, width=46, height=10)
68
tfield.pack()
69
70
root.mainloop()
71
So, the API I used is supposed to accept the zip code which is what I am collecting using:
JavaScript
1
2
1
zip_input = Entry(root, textvariable=zip, width=24, font='Arial 14 bold').pack()
2
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()
:
JavaScript
1
2
1
url = 'https://api.openweathermap.org/data/2.5/weather?zip=' + str(zip) + 'us&appid=' + api_key
2
Consider using a variable, e.g. zip_str
, instead of calling str()
multiple times.
You also might want to validate the user input.