Skip to Content
Course content

283: Practice Exercise: Building a Simple Weather API Client

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I've seen this exact snippet of code in a dozen different junior portfolios. It looks clean, it's concise, and it works perfectly—until the moment it doesn't. Let's look at this attempt to pull the current temperature from a weather API.

import requests

def get_temp(city):
    api_key = "your_api_key_here"
    url = f"http://api.openweathermap.org/data/2.5/weather?q={city}&appid={api_key}"
    response = requests.get(url)
    data = response.json()
    
    return data['main']['temp']

# This works for 'London'
print(get_temp("London")) 

# This crashes the entire program
print(get_temp("FakeCity123")) 

The 'City Not Found' KeyError

If you run the code above with a real city, it's great. But the moment you pass in a city that doesn't exist, Python throws a KeyError: 'main'. Why? Because when an API can't find the resource you're asking for, it doesn't just return an empty dictionary; it returns a JSON response explaining the error. In this case, OpenWeatherMap returns something like {"cod": "404", "message": "city not found"}.

The code blindly assumes that the 'main' key will always be there. It's a classic mistake. We're treating the "happy path" as the only path, which is a recipe for a production crash.

Guarding the API Response

To fix this, we need to stop assuming the request succeeded. The requests library gives us a very handy method called raise_for_status(). If the server returned a 4xx or 5xx error, this method will raise an HTTPError. By wrapping this in a try-except block, we can handle the failure gracefully without the whole script blowing up.

I also recommend using the .get() method for dictionaries when you aren't 100% certain a key exists, though in this specific API, checking the status code is the more robust architectural choice.

import requests

def get_temp(city):
    api_key = "your_api_key_here"
    url = f"http://api.openweathermap.org/data/2.5/weather?q={city}&appid={api_key}"
    
    try:
        response = requests.get(url)
        # This is the magic line. It triggers an exception for 404, 500, etc.
        response.raise_for_status() 
        
        data = response.json()
        return data['main']['temp']
        
    except requests.exceptions.HTTPError as http_err:
        return f"HTTP error occurred: {http_err}"
    except Exception as err:
        return f"An unexpected error occurred: {err}"

print(get_temp("London"))      # Works
print(get_temp("FakeCity123")) # Returns a readable error instead of crashing

By shifting our mindset from "I hope this works" to "I expect this might fail," we've turned a brittle script into a professional client. Remember: never trust the data coming across the wire. Whether it's a 404 from a missing city or a 500 because the API server is having a bad day, your code should handle it without panicking.




📋 Practical Task

Exercise: Building a Multi-Metric Weather Dashboard Client

Your task is to build a more comprehensive weather client. Instead of just fetching the temperature, you will create a function that retrieves and formats multiple pieces of data into a human-readable report.

Requirements:

  • Create a function called get_weather_report(city).
  • The function must fetch data from the OpenWeatherMap API (or a similar free weather API).
  • Extract the following three metrics: Temperature, Humidity, and the Weather Description (found in the 'weather' list in the response).
  • Implement a try-except block using response.raise_for_status() to handle invalid city names or connection issues.
  • If the request is successful, return a formatted string like: "In London, it is currently 15°C with 72% humidity and light rain."
  • If the request fails, return a friendly message indicating that the city could not be found.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.