PYTHON
Building a Reusable Python API Client
Create a robust and reusable Python class to interact with a RESTful API, encapsulating requests, error handling, and common patterns for cleaner integrations.
import requests
import os
class MyApiClient:
def __init__(self, base_url, api_key_env_var='MY_API_KEY'):
self.base_url = base_url
self.api_key = os.getenv(api_key_env_var)
if not self.api_key:
raise ValueError(f"API key environment variable '{api_key_env_var}' not set.")
self.headers = {
'Authorization': f'Bearer {self.api_key}',
'Content-Type': 'application/json',
'Accept': 'application/json'
}
def _request(self, method, endpoint, params=None, data=None, json=None):
url = f"{self.base_url}/{endpoint.lstrip('/')}"
try:
response = requests.request(
method,
url,
headers=self.headers,
params=params,
data=data,
json=json,
timeout=10 # Set a timeout for requests
)
response.raise_for_status() # Raises HTTPError for bad responses (4xx or 5xx)
return response.json()
except requests.exceptions.HTTPError as e:
print(f"HTTP Error: {e.response.status_code} - {e.response.text}")
raise
except requests.exceptions.ConnectionError as e:
print(f"Connection Error: {e}")
raise
except requests.exceptions.Timeout as e:
print(f"Timeout Error: {e}")
raise
except requests.exceptions.RequestException as e:
print(f"Request Error: {e}")
raise
def get(self, endpoint, params=None):
return self._request('GET', endpoint, params=params)
def post(self, endpoint, data=None, json=None):
return self._request('POST', endpoint, data=data, json=json)
def put(self, endpoint, json=None):
return self._request('PUT', endpoint, json=json)
def delete(self, endpoint):
return self._request('DELETE', endpoint)
# --- Example Usage ---
if __name__ == "__main__":
# Set a dummy API key for testing (in real app, use environment variables)
os.environ['MY_API_KEY'] = 'your_super_secret_api_key'
try:
client = MyApiClient(base_url='https://jsonplaceholder.typicode.com')
# Get a post
post = client.get('/posts/1')
print("Fetched Post:", post)
# Create a new post
new_post_data = {'title': 'foo', 'body': 'bar', 'userId': 1}
created_post = client.post('/posts', json=new_post_data)
print("Created Post:", created_post)
# Simulate an error
# This would raise an exception due to 404
# client.get('/nonexistent-endpoint')
except ValueError as e:
print(f"Configuration Error: {e}")
except requests.exceptions.RequestException as e:
print(f"API Client Error: {e}")
How it works: This Python class provides a structured way to interact with a RESTful API. It initializes with a base URL and an API key retrieved from environment variables for security. The `_request` method handles common HTTP request logic, including setting headers, timeouts, and robust error handling using `requests.exceptions`. It then exposes convenient methods like `get`, `post`, `put`, and `delete`, making API interactions clean and consistent throughout your application.