Get API Key
Register at openweathermap.org → API keys. Free tier = 1,000 calls/day.
Complete Implementation
import os, requests
from datetime import datetime
API_KEY = os.getenv("OPENWEATHER_API_KEY", "your_key_here")
BASE = "https://api.openweathermap.org/data/2.5"
def get_current(city, units="metric"):
r = requests.get(f"{BASE}/weather", params={"q": city, "appid": API_KEY, "units": units}, timeout=10)
r.raise_for_status()
return r.json()
def get_forecast(city, units="metric"):
r = requests.get(f"{BASE}/forecast", params={"q": city, "appid": API_KEY, "units": units, "cnt": 40}, timeout=10)
r.raise_for_status()
return r.json()["list"]
def display_current(d, units):
sym = "°C" if units == "metric" else "°F"
print(f"\n{'='*40}")
print(f" {d['name']}, {d['sys']['country']}")
print(f" {d['weather'][0]['description'].title()}")
print(f" Temp: {d['main']['temp']}{sym} (feels like {d['main']['feels_like']}{sym})")
print(f" Humidity: {d['main']['humidity']}% Wind: {d['wind']['speed']} m/s")
print("="*40)
def display_forecast(forecast, units):
sym = "°C" if units == "metric" else "°F"
print("\n5-Day Forecast:")
seen = set()
for entry in forecast:
dt = datetime.fromtimestamp(entry["dt"])
if dt.hour == 12 and dt.date() not in seen:
seen.add(dt.date())
print(f" {dt.strftime('%a %b %d')}: {entry['main']['temp']}{sym} {entry['weather'][0]['description']}")
city = input("City: ").strip()
units = input("Units metric/imperial [metric]: ").strip() or "metric"
try:
display_current(get_current(city, units), units)
display_forecast(get_forecast(city, units), units)
except requests.HTTPError as e:
print(f"Error {e.response.status_code}: city not found or invalid API key")export OPENWEATHER_API_KEY=your_key_here
python weather.py🏋️ Practical Exercise
Extend the weather app:
- Let the user enter any city name and fetch its current weather.
- Display temperature, conditions, and humidity in a readable format.
- Handle an invalid city or network error gracefully.
- Cache the last result so repeated lookups are instant.
🔥 Challenge Exercise
Build a richer weather tool: show a multi-day forecast, let the user pick Celsius or Fahrenheit, and keep their API key in an environment variable instead of the code. Add robust error handling for bad input, network failures, and rate limits, plus a short retry. Bonus: cache responses for a few minutes and display the data as a small chart.
📋 Summary
- This project consumes a weather REST API and displays current conditions.
- The
requestslibrary fetches data; the JSON response is parsed for the fields you need. - API keys belong in environment variables or config, never hard-coded.
- Network errors, invalid cities, and rate limits are handled gracefully.
- Caching avoids redundant calls and speeds up repeated lookups.
- It can grow with forecasts, unit switching, and charts.
Interview Questions on Building a Weather App
- How do you call a third-party REST API from Python?
- How should you store and protect an API key?
- How do you parse and use a JSON API response?
- How do you handle network errors and bad responses?
- Why and how would you cache API results?
- How do you respect API rate limits?
- How would you let users switch units or locations?
Related Topics
FAQ
Never hard-code it in the source or commit it to git. Store it in an environment variable (read with os.environ) or a .env file loaded by python-dotenv, and keep that file out of version control.
Check the response status code and body — most weather APIs return an error (e.g. 404) for unknown cities. Detect it and show a friendly message instead of crashing on missing JSON fields.
Weather changes slowly and APIs limit how many calls you can make. Caching a result for a few minutes avoids hitting rate limits, reduces latency for repeated lookups, and is gentler on the provider.
Wrap the call in try/except for requests exceptions (timeouts, connection errors), show a clear message, and optionally retry a couple of times with a short delay for transient failures.
