Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Demonstration of API using OpenWeatherMap.org

This demonstration is heavily inspired by NeuralNine’s video.
You need a free account from here.
The VS Code extension JSON viewer is recommended for viewing downloaded JSON content.

  • Set your maximum API calls to 1000 per day to make sure you are under the limit for billing.

  • To run the examples, download your API key, save it in the right folder (see below) in a file called api_key_OpenWeather, containing only the key (no spaces or “enters”).

# Imports
import datetime as dt
import requests
import json

Current weather

Common definitions to use for all requests

BASE_URL = "http://api.openweathermap.org/data/2.5/weather?"
API_KEY = open('../../../No_sync/api_key_OpenWeather','r').read()
CITY = "Ski" # Implicit geocoding is deprecated.

url = BASE_URL + "q=" + CITY + "&appid=" + API_KEY

Request current weather in chosen city

response = requests.get(url).json()
print(response)
# Write JSON to file for viewing
with open('downloads/weather.json', 'w') as f:
    json.dump(response, f, indent=4)

Conversion functions

Changing scales can make results more interpretable

# Kelvin to Celsius
def kelvin_to_celsius(temp):
    return temp - 273.15

# Meters per second to knots
def mps_to_knots(speed):
    return speed * 1.943844
# Current temperature
temp_kelvin = response['main']['temp']
temp_celsius = kelvin_to_celsius(temp_kelvin)
print(f"The current temperature in {CITY} is {temp_celsius:.1f} °C")
# Sunrise and sunset today in local time
sunrise = dt.datetime.fromtimestamp(response['sys']['sunrise'])
sunset = dt.datetime.fromtimestamp(response['sys']['sunset'])
print(f"Sunrise today is at {sunrise:%H:%M} and sunset is at {sunset:%H:%M}")
# Wind direction and speed
wind_knots = mps_to_knots(response['wind']['speed'])
print(f"Wind today is from {response['wind']['deg']}° at {round(wind_knots,1)} knots")

Forecasted weather

Common definitions to use for all requests

BASE_URL = "https://api.openweathermap.org/data/2.5/forecast?"
CITY = "Agadir"

urlF = BASE_URL + "q=" + CITY + "&appid=" + API_KEY

Request forecasted weather in chosen city

responseF = requests.get(urlF).json()
#print(json.dumps(responseF, indent=4))
print(responseF)
# Write JSON to file for viewing
with open('downloads/forecast.json', 'w') as f:
    json.dump(responseF, f, indent=4)

When and what?

Check contents and time stamps

# Content of responseF
responseF.keys()
# Number of forecasts
print(len(responseF["list"]))
# Print forecast times
for forecast in responseF["list"]:
    print(forecast["dt_txt"])

Make plots of omnipresent measurements and events

We will later look at missing data, data only sporadically appearing and so on.

# Air pressure per period
pressures = []
timestamps = []
for forecast in responseF["list"]:
    pressures.append(forecast["main"]["pressure"])
    timestamps.append(dt.datetime.fromtimestamp(forecast["dt"]))
import matplotlib.pyplot as plt
plt.bar(timestamps, pressures)
plt.xticks(rotation=45)
plt.ylim(960, 1050)
plt.grid()
plt.ylabel("Air pressure (hPa)")
plt.title(f"Forecasted air pressure in {CITY}")
plt.show()

Exercise

  • Make a new forecast request for your own hometown. Call your response something else than responseF.

  • If available, plot the humidity like we did with air pressure.

Precipitation

  • ... comes in two main flavours: rain and snow.

  • We need to check which is present and set to zero if it is abscent.

rain = []
snow = []
for forecast in responseF["list"]:
    try: # Check if rain is present in forecast
        rain.append(forecast["rain"]["3h"])
    except KeyError:
        rain.append(0)
    try: # Check if snow is present in forecast
        snow.append(forecast["snow"]["3h"])
    except KeyError:
        snow.append(0)
# Stacked bar chart with rain and snow
plt.bar(timestamps, rain, label="Rain")
plt.bar(timestamps, snow, label="Snow")
plt.xticks(rotation=45)
plt.grid()
plt.ylabel("Precipitation (mm)")
plt.title(f"Forecasted precipitation in {CITY}")
plt.legend()
plt.show()

Live coding

  • Create a Streamlit app with these elements:

    • City selector (can we make use og the Geocoding API?)

    • Property selector

    • Print selected data