base.py 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. """
  4. API客户端基类
  5. """
  6. from abc import ABC, abstractmethod
  7. from typing import Any, Optional
  8. import logging
  9. import time
  10. from functools import wraps
  11. class BaseAPIClient(ABC):
  12. """API客户端基类,提供统一的重试、缓存、日志功能"""
  13. def __init__(
  14. self,
  15. api_name: str,
  16. max_retries: int = 3,
  17. retry_delay: float = 2.0,
  18. logger: Optional[logging.Logger] = None
  19. ):
  20. self.api_name = api_name
  21. self.max_retries = max_retries
  22. self.retry_delay = retry_delay
  23. self.logger = logger or logging.getLogger(api_name)
  24. def with_retry(self, func):
  25. """重试装饰器"""
  26. @wraps(func)
  27. def wrapper(*args, **kwargs):
  28. for attempt in range(1, self.max_retries + 1):
  29. try:
  30. return func(*args, **kwargs)
  31. except Exception as e:
  32. self.logger.warning(
  33. f"[{self.api_name}] Attempt {attempt}/{self.max_retries} failed: {e}"
  34. )
  35. if attempt < self.max_retries:
  36. time.sleep(self.retry_delay)
  37. else:
  38. self.logger.error(f"[{self.api_name}] All retries failed: {e}")
  39. raise
  40. return None
  41. return wrapper
  42. @abstractmethod
  43. def call(self, *args, **kwargs) -> Any:
  44. """具体的API调用逻辑,子类实现"""
  45. pass