-
Section 1: Getting Started
-
Section 2: Core Syntax and Data Types
-
Section 3: Collections
-
39: Set Operations: Union, Intersection, Difference
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Turtle Graphics and Early Practice Projects
-
Section 7: Working with Files and I/O
-
Section 8: Regular Expressions
-
Section 9: Object-Oriented Python
-
Section 10: Error Handling
-
Section 11: Modules and Packages
-
Section 12: Iterators, Generators, and Functional Tools
-
Section 13: Decorators and Metaprogramming
-
Section 14: Concurrency and Parallelism
-
Section 15: Working with Dates, Times, and Numbers
-
Section 16: Standard Library Deep Dive I: Data Structures
-
Section 17: Standard Library Deep Dive II: System and Introspection
-
Section 18: Standard Library Deep Dive III: Security and Encoding
-
Section 19: Standard Library Deep Dive IV: Text and Data Utilities
-
Section 20: Networking and Web Basics
-
Section 21: Working with Databases
-
Section 22: Testing and Quality
-
Section 23: Advanced Typing
-
Section 24: Context Managers and Resource Handling
-
Section 25: Text, Unicode, and Binary Data
-
Section 26: More Functional and Iteration Tools
-
Section 27: Data Validation and Configuration
-
Section 28: Working with Images and Media
-
Section 29: Property-Based and Documentation Testing
-
Section 30: Packaging and Deployment
-
Section 31: Performance and Internals
-
Section 32: Design Patterns in Python
-
Section 33: GUI Programming
-
Section 34: Security Basics
-
Section 35: Data Structures and Algorithms
-
Section 36: Practical Projects
-
Section 37: Capstone Projects
-
Section 38: Interview and Algorithm Practice
-
Section 39: Writing Idiomatic Python
283: Practice Exercise: Building a Simple Weather API Client
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 theWeather Description(found in the 'weather' list in the response). - Implement a
try-exceptblock usingresponse.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.
There are no comments for now.