Get Weather Forecasts And Show It On A Chart Using Python 3


Intermediate

Weather forecast data is available from a range fo online services with different patterns which can generally be accessed via an API call from Python. In this article we’ll explore how to extract the weather data from openweathermap.org and then display this on a map so that you can get a visual view of weather locations. This can be useful for a range of applications or as an additional widget for your next web project.

Hereby, we’re going to use python3 to get all the data about weather forecast. For this, various weather APIs can be bring into our purpose some of which are listed below:-

Using OpenWeatherMap to get weather forecasts in Python

First thing first, I’m using here one of the convenient and freely available openweathermap that provides weather data, including current weather data, forecasts, and historical data to the developers. It provides an API with JSON, XML and HTML endpoints and a limited free usage tier.

Users can request current weather information, extended forecasts and graphical maps (showing cloud cover, wind speed, pressure and precipitation).

Step 1: Get API Key from Open Weather Map

To use this current weather data API, one must need the API key, which can be obtained from https://openweathermap.org/api

See options for the API keys. For this tutorial I chose the Climatic Forecast 30 days

You will need to create an account on openweathermap.org then only you can use the APIs. You can choose as per your requirement and go for it. I have used the free API for this tutorial. You can simply signup with your email and get API key which is will be used to get the details.

You can chose the free tier if you have <1m calls per month. Please note, the Free Tier only supports a few weather services for forecasts. You can click on Get API Key on Free Tier.
You can then enter your user details to get the API key
You will have a final question on usage which looks like more for statistical information rather than anything else

Once created, you can then go to the menu: My API Keys from the user menu.

Once in the API Key area, you can use the default key, or generate a new key (if you’re generating a new key, the key name is not important).

Now that you have the key, you can then call the API to test if you can get the data for a given location.

Step 2: Testing Weather Forecast using Lat Long

In order to get the weather for a given location, you can use the Latitude (Lat) and the Longitude (Long) of a given location. The easiest way to get the Lat Long is to open up google maps, then search for a given location, then right click to get the Lat Long. The first number is a Latitude (e.g. in screenshot below 22.30130 is the Latitude)

Here’s also another handy tool to get the lat long: https://www.tytai.com/gmap/

Once you’ve got the Lat Long, then you can make a request to the API. The API we will be using is called “OneCall”. You can find the documentation here: https://openweathermap.org/api/one-call-api

Here’s a code snippet of code by passing in the Lat Long:

#weather_forecast.py
import requests

OPEN_WEATHER_MAP_APIKEY = '444ea47a72e5390ca5e538dca754b606'

def get_weather_data_by_location( lat, long):
	url = f'https://api.openweathermap.org/data/2.5/onecall?lat={lat}&lon={long}&appid={OPEN_WEATHER_MAP_APIKEY}&units=metric'
	print(f"Getting data via {url}")
	r = requests.get(url)
	return r.json()
	if r.status_code == 200:
		return r.json()
	else:
		return None

if __name__ == '__main__':
	print("Getting Weather Data")
	print( get_weather_data_by_location( '22.300910042194783', '114.17070449064359') )

And here’s the output:

As you can see, there is a LOT of data that comes out. We’ll make a slight update in order to just get the right fields. To make it more readable you can use an online JSON viewer by first running the program again, but then outputting the data to a file:

python3 weather_forecast.py > output_file.json

This will output all the data to a file called “output_file.json”. You can then open the file and copy and paste the data to Online JSON viewer like so:

You can then go to the “Viewer” tab to see formatted json.

Online json viewer

There are a few things to note here:

  • The daily element contains 8 days of data. Records [0] is the current day at <current date> 4AM (GMT timezone). Records [1] is the <next day> 4AM (GMT timezone). Record [7] is the <7th day> 4AM (GMT timezone).
  • The field “dt” is the datetime field in unix epoch time (epoch time is the number of seconds since 1st Jan 1970). You can use a quick converter from epoch time at https://www.epochconverter.com
Online epoch coverter from https://www.epochconverter.com/

To make things simpler for us, we will change the code to just get the above information and also to convert the time from epoch time to local time.

Step 3: Formatting the returned data

The data that is returned from the query is in a dictionary, so let’s just get the following key fields.

Viewed on http://jsonviewer.stack.hu/

Hence, the code snippet to print just this data will be as follows:

##.. as per previous code above

if __name__ == '__main__':
	print("Getting Weather Data")
	json_data =  get_weather_data_by_location( '22.300910042194783', '114.17070449064359') 

	for index in range( 1, 8):
		print( f" Day [+{index}] {json_data['daily'][index]['dt']} = { json_data['daily'][index]['temp']['day']} " )

Output will be as follows:

Next, let’s convert the epoch time to local time. To do this, we will use the timezone module pytz and the datetime function. Please note you have to include the libraries datetime and pytz.

import datetime, pytz
##.. as per previous code above

if __name__ == '__main__':
	print("Getting Weather Data")
	json_data =  get_weather_data_by_location( '22.300910042194783', '114.17070449064359') 

	for index in range( 1, 8):
                local_time = datetime.datetime.fromtimestamp( json_data['daily'][index]['dt'] , tz=pytz.timezone('Asia/Singapore'))
		str_time = local_time.strftime( '%Y-%m-%d %a' )
		print( f" Day [+{index}] {str_time} = { json_data['daily'][index]['temp']['day']} " )

In the above code, we call “datetime.datetime.fromtimestamp” and pass in the epoch time, and a local timezone you want to convert from. You can find all the list of valid timezones on wikipedia timezone list and chose your own timezone.

The “local_time.strftime” will then format the time. We are just getting the Year-Month-Date DayOfWeek.

Output as follows:

Let’s finally view this as a graph online.

Step 4: View the daily forecast on a graph online

In order to show this as a bar chart, we are going to use an online service called Quick Chart which is developed by Ian Webster. The service helps to generate a chart online via a query link or to download an image file.

First install the quickchart library using pip or pip3 (depends on your installation):

pip3 install quickchart.io

Then from the imported class QuickChart, you can assign the parameters to draw the chart via the field .config. Once that’s done, you can get a URL and a downloaded image.

The following helper function takes in the same dictionary from the original json data from the openweathermap website, and then inserts it into the chart.

from quickchart import QuickChart

#as per previous code...

def get_quick_chart( json_data , output_file):
  qc = QuickChart() 
  qc.width = 500 #set width and height of chart in pixels
  qc.width = 500

  labels = []	#Declare to hold the x-axis tick labels
  weather_readings = []  #get the data labels
  
  #Just as per before, convert date, and get the forecast days
  for index in range( 1, 8):
    local_time = datetime.datetime.fromtimestamp(json_data['daily'][index]['dt'] , tz=pytz.timezone('Asia/Singapore'))
    labels.append(   local_time.strftime( '%a %d/%m ' ) )
    weather_readings.append( round( json_data['daily'][index]['temp']['day'] ,1) )

   qc.config = """{ type: 'line',
                    data: { labels: """ + str( labels ) + """,
		    datasets: [ { 
			        backgroundColor: 'rgb(255, 99, 132)', 
                                data: """ + str( weather_readings) + """,
				lineTension: 0.4,
				fill: false,
				}
			       ],
			    },
		 options: {
                       title: { display: true,  text: '7-Day Weather Forecast' }, 
		       legend: { display: false}, 
  		       scales: { yAxes: [ { scaleLabel: 
			 { display: true, 
                           labelString: 'Temperature Degrees Celcius' } } ]},
		  	plugins: { 
                            datalabels: {
                               display: true,
			       align: 'bottom',
                               backgroundColor: '#ccc',
                               borderRadius: 3
                 	      },
                                }
                           },
			 }""" 
  print(qc.get_short_url()) 	#Print out the chart URL
  qc.to_file(output_file)	#Save to a file

With the above, you will get a URL with the chart, and also an image which is downloaded to the current working directory as follows:

Conclusions and full code

So we managed to get a weather forecast, and then also show this on a chart using QuickCharts.

You can see the full code from the GitHub repo from here

Happy Coding!

Get Notified of New Posts

We post regularly here. Get notifications of when new posts are available directly into your inbox and learn new tips and tricks you would only stumble across when you really are stuck!

It takes less than 30 seconds to subscribe now:

Leave a Reply

Your email address will not be published. Required fields are marked *

Recent Content