In today’s blog, we’ll dive into creating a dynamic weather widget using Python’s Dash framework. This widget will fetch live weather data and display it alongside engaging animations, providing a visually appealing and informative user experience.
Prerequisites
Before we begin, make sure you have Python installed on your system. You’ll also need to install Dash and other necessary libraries using pip:
pip install dash dash-bootstrap-components requests dash-extensions dash-leaflet
Setting Up the Project
Let’s start by importing the required libraries and setting up our Dash application.
import dash
import dash_bootstrap_components as dbc from dash import html, dcc import requests from dash.dependencies import Input, Output from dash_extensions import Lottie # For animations import dash_leaflet as dl # For the map
Next, initialize the Dash app and include Bootstrap CSS for styling:
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
Fetching Live Weather Data
To fetch live weather data, we’ll use an API provided by Open Meteo:
def get_weather():
url = "https://api.open-meteo.com/v1/forecast"
params = {"latitude": 13.0827, "longitude": 80.2707, "current_weather": True}
response = requests.get(url, params=params)
weather_data = response.json()
if "current_weather" in weather_data:
current_weather = weather_data["current_weather"]
temperature = current_weather["temperature"]
windspeed = current_weather["windspeed"]
winddirection = current_weather["winddirection"]
weather_code = current_weather["weathercode"]
weather_info = {
"Temperature": f"{temperature}°C",
"Windspeed": f"{windspeed} km/h",
"Winddirection": f"{winddirection}°",
"Weathercode": weather_code,
}
return weather_info
else:
return None
Building the User Interface
Now, let’s construct the layout of our Dash application. We’ll use Bootstrap components for structuring and styling our weather widget
.app.layout = html.Div(
[ html.Script( src="https://unpkg.com/@dotlottie/player-component@latest/dist/dotlottie-player.mjs",
type="module",
),
dbc.Container(
[
dbc.Row(
dbc.Col(
html.H1("Weather Widget", className="text-center my-4"),
width=12,
),
justify="center",
),
dbc.Row(
[
# Temperature card
dbc.Col(
dbc.Card(
[
dbc.CardHeader("Temperature"),
dbc.CardBody(
[
html.Div(
Lottie(
options=dict(
loop=True, autoplay=True
),
width="50%",
height="50%",
url=weather_icons["temperature"],
),
),
html.Div(
id="temperature", className="value"
),
]
),
],
className="card mb-4",
),
width=3,
),
# Windspeed card
dbc.Col(
dbc.Card(
[
dbc.CardHeader("Windspeed"),
dbc.CardBody(
[
html.Div(
Lottie(
options=dict(
loop=True, autoplay=True
),
width="50%",
height="50%",
url=weather_icons["windspeed"],
),
),
html.Div(id="windspeed", className="value"),
]
),
],
className="card mb-4",
),
width=3,
),
# Winddirection card
dbc.Col(
dbc.Card(
[
dbc.CardHeader("Winddirection"),
dbc.CardBody(
[
html.Div(
Lottie(
options=dict(
loop=True, autoplay=True
),
width="50%",
height="50%",
url=weather_icons["winddirection"],
),
),
html.Div(
id="winddirection", className="value"
),
]
),
],
className="card mb-4",
),
width=3,
),
# Weathercode and Map card
dbc.Col(
dbc.Card(
[
dbc.CardHeader("Weathercode and Location"),
dbc.CardBody(
[
html.Div(
Lottie(
options=dict(
loop=True, autoplay=True
),
width="50%",
height="50%",
url=weather_icons["weathercode"],
),
),
html.Div(
id="weathercode", className="value"
),
dl.Map(
style={
"width": "100%",
"height": "300px",
},
center=[13.0827, 80.2707],
zoom=10,
children=[
dl.TileLayer(),
dl.Marker(
position=[13.0827, 80.2707],
children=[
dl.Tooltip(
"Chennai, India"
),
dl.Popup(
[
html.H1("Chennai"),
html.P(
"Weather data location."
),
]
),
],
),
],
),
]
),
],
className="card mb-4",
),
width=3,
),
],
justify="center",
),
dcc.Interval(
id="interval-component", interval=60000, n_intervals=0
), # Update every 60 seconds
],
fluid=True,
className="bg-dark text-white", # Dark mode styling
),
],
className="full-page",
)
Live Updates with Callbacks:
To ensure the weather information updates dynamically, we’ll set up a callback function that updates the data every minute (dcc.Interval).
@app.callback(
[
Output("temperature", "children"),
Output("windspeed", "children"),
Output("winddirection", "children"),
Output("weathercode", "children"),
],
Input("interval-component", "n_intervals"),
)
def update_weather(n):
weather_info = get_weather()
if weather_info is None:
return ["Data not available!"] * 4
return [
weather_info["Temperature"],
weather_info["Windspeed"],
weather_info["Winddirection"],
weather_info["Weathercode"],
]
Styling with CSS
Lastly, we’ll add custom CSS to style our application, ensuring it looks sleek and professional.
body {
margin: 0;
padding: 0;
height: 100%;
background: url('https://lottie.host/embed/710935a8-5df6-4baf-8461-b9dbf1cc35e0/Bw1LlmZoFA.json') no-repeat center center fixed;
background-color: #181818;
color: white;
}
.full-page {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
}
.card {
background-color: #282828;
border: none;
color: white;
}
.card-header {
background-color: #282828;
border-bottom: 1px solid #444;
}
.card-body {
display: flex;
flex-direction: column;
align-items: center;
}
.value {
font-size: 1.5rem;
margin-top: 1rem;
}
.bg-dark {
background-color: #181818 !important;
}
Conclusion
In this blog, we’ve walked through the process of creating a weather widget using Dash and Python. By leveraging APIs for weather data and integrating dynamic updates with Dash’s callback functions, we’ve created a responsive and visually appealing application. Feel free to customize the widget further or explore additional features to enhance its functionality!
Chakilam Satya Lohit
Customer Success Manager
Toolfe – IT & Process Automation