Python Snippets

Real-time Currency Converter with Exchange Rate Caching

import requests
import json
import os
from datetime import datetime, timedelta
from typing import Dict, Optional

class CurrencyConverter:
    def __init__(self, api_key: str, cache_duration_hours: int = 1):
        """
        Initialize the CurrencyConverter with API key and cache settings.
        
        Args:
            api_key (str): Your ExchangeRate-API key
            cache_duration_hours (int): How long to cache exchange rates (default: 1 hour)
        """
        self.api_key = api_key
        self.cache_duration = timedelta(hours=cache_duration_hours)
        self.cache_file = "exchange_rates_cache.json"
        self.base_url = f"https://v6.exchangerate-api.com/v6/{api_key}/latest/USD"
        
    def _load_cache(self) -> Dict:
        """Load exchange rates from cache file if it exists and is valid."""
        if not os.path.exists(self.cache_file):
            return {}
            
        try:
            with open(self.cache_file, 'r') as f:
                cache_data = json.load(f)
                
            # Check if cache is still valid
            cache_time = datetime.fromisoformat(cache_data.get('timestamp', '2000-01-01T00:00:00'))
            if datetime.now() - cache_time < self.cache_duration:
                return cache_data
            else:
                return {}
        except (json.JSONDecodeError, KeyError):
            return {}
    
    def _save_cache(self, data: Dict):
        """Save exchange rates to cache file with timestamp."""
        data['timestamp'] = datetime.now().isoformat()
        with open(self.cache_file, 'w') as f:
            json.dump(data, f)
    
    def _fetch_exchange_rates(self) -> Dict:
        """Fetch latest exchange rates from API."""
        try:
            response = requests.get(self.base_url)
            response.raise_for_status()
            data = response.json()
            
            if data.get('result') == 'success':
                # Save to cache
                self._save_cache(data)
                return data
            else:
                raise Exception(f"API Error: {data.get('error-type', 'Unknown error')}")
        except requests.RequestException as e:
            raise Exception(f"Network error: {str(e)}")
    
    def get_exchange_rates(self) -> Dict:
        """Get exchange rates, either from cache or API."""
        # Try to load from cache first
        cached_data = self._load_cache()
        if cached_data:
            return cached_data
        
        # If cache is invalid/expired, fetch from API
        return self._fetch_exchange_rates()
    
    def convert(self, amount: float, from_currency: str, to_currency: str) -> float:
        """
        Convert amount from one currency to another.
        
        Args:
            amount (float): Amount to convert
            from_currency (str): Source currency code (e.g., 'USD')
            to_currency (str): Target currency code (e.g., 'EUR')
            
        Returns:
            float: Converted amount
        """
        rates_data = self.get_exchange_rates()
        rates = rates_data.get('conversion_rates', {})
        
        # Validate currencies
        if from_currency not in rates:
            raise ValueError(f"Unsupported currency: {from_currency}")
        if to_currency not in rates:
            raise ValueError(f"Unsupported currency: {to_currency}")
        
        # Convert to USD first (base currency)
        usd_amount = amount / rates[from_currency]
        
        # Convert from USD to target currency
        result = usd_amount * rates[to_currency]
        
        return round(result, 2)

# Example usage
if __name__ == "__main__":
    # Replace with your actual API key from https://www.exchangerate-api.com/
    API_KEY = "your_api_key_here"
    
    converter = CurrencyConverter(API_KEY)
    
    try:
        # Convert 100 USD to EUR
        result = converter.convert(100, 'USD', 'EUR')
        print(f"100 USD = {result} EUR")
        
        # Convert 50 EUR to GBP
        result = converter.convert(50, 'EUR', 'GBP')
        print(f"50 EUR = {result} GBP")
        
        # Get all available exchange rates
        rates = converter.get_exchange_rates()
        print(f"Available currencies: {len(rates['conversion_rates'])}")
        
    except Exception as e:
        print(f"Error: {e}")

What This Code Does

This Python snippet creates a CurrencyConverter class that handles real-time currency conversion with intelligent caching. It connects to the ExchangeRate-API service to fetch current exchange rates and automatically caches them locally to minimize API calls and improve performance.

Key Features

Why It’s Useful

  1. Cost Efficiency: Reduces API calls by caching results, which is important since many currency conversion services have rate limits or charge per request
  2. Performance: Cached data loads instantly, eliminating network latency for repeated conversions
  3. Accuracy: Always uses up-to-date exchange rates (within your cache window)
  4. Reliability: Handles network failures gracefully and provides clear error messages
  5. Reusability: Easy to integrate into any application requiring currency conversion

How to Run

  1. Get a free API key from ExchangeRate-API (no credit card required)
  2. Replace your_api_key_here in the example with your actual API key
  3. Install the requests library: pip install requests
  4. Run the script

Usage Examples

The converter can handle conversions between any supported currencies:

The cache file automatically stores exchange rates in a JSON file, which persists between runs and invalidates itself after the specified duration.