🔗 Handling API Requests
APIs (Application Programming Interfaces) let you fetch data from web services, integrate with external platforms, and build connected applications. Python makes it easy to work with RESTful APIs and process JSON responses.
import urllib.request
import json
# Simple API request using built-in urllib
def get_api_data(url):
try:
with urllib.request.urlopen(url) as response:
data = response.read()
return json.loads(data)
except Exception as e:
print(f"Error fetching data: {e}")
return None
# Example with a placeholder API
api_url = "https://jsonplaceholder.typicode.com/posts/1"
post_data = get_api_data(api_url)
if post_data:
print(f"Post ID: {post_data['id']}")
print(f"Title: {post_data['title']}")
print(f"Body: {post_data['body'][:100]}...")
🎯 Understanding API Requests
APIs use HTTP methods to communicate, with JSON being the most common data format for responses.
Basic GET Requests
import urllib.request
import urllib.parse
import json
def fetch_user_posts(user_id):
"""Fetch posts for a specific user"""
base_url = "https://jsonplaceholder.typicode.com/posts"
params = {'userId': user_id}
# Build URL with parameters
url = f"{base_url}?{urllib.parse.urlencode(params)}"
try:
with urllib.request.urlopen(url) as response:
if response.status == 200:
data = json.loads(response.read())
return data
else:
print(f"Error: HTTP {response.status}")
return []
except Exception as e:
print(f"Request failed: {e}")
return []
def fetch_weather_data():
"""Simulate weather API call"""
# Mock weather data (replace with real API)
mock_data = {
"temperature": 22,
"humidity": 65,
"conditions": "Partly Cloudy",
"location": "San Francisco"
}
return mock_data
# Test the functions
posts = fetch_user_posts(1)
print(f"Found {len(posts)} posts for user 1")
if posts:
print(f"First post: {posts[0]['title']}")
weather = fetch_weather_data()
print(f"Weather: {weather['temperature']}°C, {weather['conditions']}")
POST Requests with Data
import urllib.request
import urllib.parse
import json
def create_post(title, body, user_id):
"""Create a new post via API"""
url = "https://jsonplaceholder.typicode.com/posts"
# Prepare data
post_data = {
'title': title,
'body': body,
'userId': user_id
}
# Convert to JSON and encode
json_data = json.dumps(post_data)
data = json_data.encode('utf-8')
# Create request with headers
req = urllib.request.Request(url, data=data)
req.add_header('Content-Type', 'application/json')
try:
with urllib.request.urlopen(req) as response:
if response.status == 201: # Created
result = json.loads(response.read())
return result
else:
print(f"Error: HTTP {response.status}")
return None
except Exception as e:
print(f"Request failed: {e}")
return None
def send_form_data(name, email):
"""Send form data (application/x-www-form-urlencoded)"""
url = "https://httpbin.org/post" # Test endpoint
# Prepare form data
form_data = {
'name': name,
'email': email
}
# Encode as form data
data = urllib.parse.urlencode(form_data).encode('utf-8')
req = urllib.request.Request(url, data=data)
req.add_header('Content-Type', 'application/x-www-form-urlencoded')
try:
with urllib.request.urlopen(req) as response:
result = json.loads(response.read())
return result.get('form', {})
except Exception as e:
print(f"Form submission failed: {e}")
return {}
# Test POST request
new_post = create_post("My New Post", "This is the content of my post.", 1)
if new_post:
print(f"Created post with ID: {new_post['id']}")
# Test form submission
form_result = send_form_data("Alice Johnson", "alice@example.com")
print(f"Form submission result: {form_result}")
📋 HTTP Status Codes Reference
Code | Meaning | Description |
---|---|---|
200 | OK | Request successful |
201 | Created | Resource created successfully |
400 | Bad Request | Invalid request format |
401 | Unauthorized | Authentication required |
404 | Not Found | Resource doesn't exist |
500 | Server Error | Internal server error |
🔧 Error Handling and Retries
Robust API Request Handler
import urllib.request
import urllib.error
import json
import time
def api_request_with_retry(url, method='GET', data=None, headers=None, max_retries=3):
"""Make API request with retry logic and error handling"""
if headers is None:
headers = {}
# Set default headers
if 'User-Agent' not in headers:
headers['User-Agent'] = 'Python API Client 1.0'
for attempt in range(max_retries):
try:
# Create request
req = urllib.request.Request(url, data=data, headers=headers, method=method)
with urllib.request.urlopen(req, timeout=10) as response:
status_code = response.status
response_data = response.read()
# Parse JSON if content type indicates JSON
content_type = response.headers.get('Content-Type', '')
if 'application/json' in content_type:
try:
parsed_data = json.loads(response_data)
except json.JSONDecodeError:
parsed_data = response_data.decode('utf-8')
else:
parsed_data = response_data.decode('utf-8')
return {
'success': True,
'status_code': status_code,
'data': parsed_data,
'headers': dict(response.headers)
}
except urllib.error.HTTPError as e:
status_code = e.code
error_msg = f"HTTP {status_code}: {e.reason}"
if status_code >= 500 and attempt < max_retries - 1:
# Retry on server errors
print(f"Server error, retrying in {2 ** attempt} seconds...")
time.sleep(2 ** attempt)
continue
else:
return {
'success': False,
'status_code': status_code,
'error': error_msg
}
except urllib.error.URLError as e:
error_msg = f"Network error: {e.reason}"
if attempt < max_retries - 1:
print(f"Network error, retrying in {2 ** attempt} seconds...")
time.sleep(2 ** attempt)
continue
else:
return {
'success': False,
'error': error_msg
}
except Exception as e:
return {
'success': False,
'error': f"Unexpected error: {str(e)}"
}
return {
'success': False,
'error': f"Max retries ({max_retries}) exceeded"
}
# Test robust API handler
def test_api_endpoints():
"""Test various API scenarios"""
# Test successful request
result = api_request_with_retry("https://jsonplaceholder.typicode.com/posts/1")
if result['success']:
print(f"Success: Got post with title: {result['data']['title']}")
else:
print(f"Failed: {result['error']}")
# Test 404 error
result = api_request_with_retry("https://jsonplaceholder.typicode.com/posts/99999")
if result['success']:
print("Success: Found post")
else:
print(f"Expected 404: {result['error']}")
test_api_endpoints()
🎯 Key Takeaways
🚀 What's Next?
Learn how to work with databases to store and query structured data efficiently.
Continue to: Work with Databases
Was this helpful?
Track Your Learning Progress
Sign in to bookmark tutorials and keep track of your learning journey.
Your progress is saved automatically as you read.