Python Weather Integration with WeatherAPI: Complete Developer Tutorial
Python developers looking to add weather functionality to their applications have a powerful ally in WeatherAPI. With over 850,000 developers already using our service, WeatherAPI provides reliable weather data with an average response time of just 200ms across 4M+ locations worldwide.
This tutorial will walk you through integrating WeatherAPI with Python using the popular requests library, covering current weather, forecasts, and proper error handling.
Getting Started
First, you’ll need a WeatherAPI key. Sign up for free to get 100,000 API calls per month with no credit card required.
Install the requests library if you haven’t already:
pip install requests
Basic Setup and Configuration
Let’s start with a basic Python class to handle our WeatherAPI interactions:
import requests
import json
from typing import Dict, Optional
class WeatherAPI:
def __init__(self, api_key: str):
self.api_key = api_key
self.base_url = "https://api.weatherapi.com/v1"
def _make_request(self, endpoint: str, params: Dict) -> Optional[Dict]:
"""Make HTTP request to WeatherAPI with error handling"""
params['key'] = self.api_key
try:
response = requests.get(f"{self.base_url}/{endpoint}", params=params)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"API request failed: {e}")
return None
Getting Current Weather Data
The current weather endpoint (/current.json) provides real-time conditions including temperature, wind, humidity, UV index, and air quality data:
def get_current_weather(self, location: str) -> Optional[Dict]:
"""Get current weather for a location"""
params = {
'q': location,
'aqi': 'yes' # Include air quality data
}
data = self._make_request('current.json', params)
if data:
current = data['current']
return {
'location': data['location']['name'],
'country': data['location']['country'],
'temperature_c': current['temp_c'],
'temperature_f': current['temp_f'],
'condition': current['condition']['text'],
'humidity': current['humidity'],
'wind_kph': current['wind_kph'],
'uv': current['uv'],
'air_quality': current.get('air_quality', {})
}
return None
# Usage example
weather = WeatherAPI('YOUR_API_KEY')
current_weather = weather.get_current_weather('London')
if current_weather:
print(f"Temperature in {current_weather['location']}: {current_weather['temperature_c']}°C")
Fetching Weather Forecasts
The forecast endpoint (/forecast.json) provides up to 14 days of weather predictions with hourly breakdowns:
def get_forecast(self, location: str, days: int = 3) -> Optional[Dict]:
"""Get weather forecast for specified days (1-14)"""
if not 1 <= days <= 14:
raise ValueError("Days must be between 1 and 14")
params = {
'q': location,
'days': days,
'aqi': 'no',
'alerts': 'yes' # Include weather alerts
}
data = self._make_request('forecast.json', params)
if data:
forecast_days = []
for day in data['forecast']['forecastday']:
forecast_days.append({
'date': day['date'],
'max_temp_c': day['day']['maxtemp_c'],
'min_temp_c': day['day']['mintemp_c'],
'condition': day['day']['condition']['text'],
'chance_of_rain': day['day']['daily_chance_of_rain'],
'sunrise': day['astro']['sunrise'],
'sunset': day['astro']['sunset']
})
return {
'location': data['location']['name'],
'forecast': forecast_days,
'alerts': data.get('alerts', {}).get('alert', [])
}
return None
Advanced Error Handling and Rate Limiting
Production applications need robust error handling and respect for API limits. Here's an enhanced version with retry logic and better error management:
import time
from functools import wraps
def retry_on_failure(max_retries: int = 3, delay: float = 1.0):
"""Decorator for retrying failed API calls"""
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
for attempt in range(max_retries):
result = func(*args, **kwargs)
if result is not None:
return result
if attempt < max_retries - 1:
time.sleep(delay * (2 ** attempt)) # Exponential backoff
return None
return wrapper
return decorator
class WeatherAPIException(Exception):
"""Custom exception for WeatherAPI errors"""
pass
# Enhanced request method with detailed error handling
@retry_on_failure(max_retries=3)
def _make_request(self, endpoint: str, params: Dict) -> Optional[Dict]:
params['key'] = self.api_key
try:
response = requests.get(
f"{self.base_url}/{endpoint}",
params=params,
timeout=10
)
if response.status_code == 401:
raise WeatherAPIException("Invalid API key")
elif response.status_code == 400:
raise WeatherAPIException("Bad request - check location parameter")
elif response.status_code == 403:
raise WeatherAPIException("API key quota exceeded")
response.raise_for_status()
return response.json()
except requests.exceptions.Timeout:
print("Request timeout - retrying...")
return None
except requests.exceptions.RequestException as e:
print(f"Network error: {e}")
return None
Complete Usage Example
# Complete example with error handling
def main():
# Initialize with your API key
weather = WeatherAPI('YOUR_API_KEY')
try:
# Get current weather
current = weather.get_current_weather('New York')
if current:
print(f"Current: {current['temperature_c']}°C, {current['condition']}")
# Get 5-day forecast
forecast = weather.get_forecast('New York', days=5)
if forecast:
for day in forecast['forecast']:
print(f"{day['date']}: {day['min_temp_c']}°C - {day['max_temp_c']}°C")
except WeatherAPIException as e:
print(f"WeatherAPI error: {e}")
if __name__ == "__main__":
main()
Next Steps
This tutorial covered the fundamentals, but WeatherAPI offers much more. Explore historical weather data, marine conditions, astronomy data, and sports information. For production applications, consider our paid plans starting at just $7/month for 3 million calls.
Ready to start building? Get your free API key today and join over 850,000 developers using WeatherAPI worldwide.
