From 1d732844e31bcf7af5f62a6688e224e1d991a37f Mon Sep 17 00:00:00 2001 From: subuhui <437232628@qq.com> Date: Tue, 24 Feb 2026 17:42:00 +0800 Subject: [PATCH] retry --- data/database.py | 4 +++- data/fetcher.py | 41 +++++++++++++++++++++++++++-------------- 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/data/database.py b/data/database.py index 60b0ff5..06751cf 100644 --- a/data/database.py +++ b/data/database.py @@ -26,7 +26,9 @@ class DatabaseManager: password = os.getenv('MYSQL_PASSWORD') database = os.getenv('MYSQL_DB') self._engine = create_engine( - f"mysql+pymysql://{user}:{password}@{host}:{port}/{database}?charset=utf8mb4" + f"mysql+pymysql://{user}:{password}@{host}:{port}/{database}?charset=utf8mb4", + pool_pre_ping=True, + pool_recycle=3600 ) return self._engine diff --git a/data/fetcher.py b/data/fetcher.py index 62d371a..48c9303 100644 --- a/data/fetcher.py +++ b/data/fetcher.py @@ -1,6 +1,7 @@ """从Binance获取加密货币OHLCV数据""" import os +import time from datetime import datetime, timedelta from pathlib import Path from typing import Optional, Literal @@ -69,7 +70,8 @@ class BinanceDataFetcher: timeframe: Literal['1h', '15m'], start_date: Optional[str] = None, end_date: Optional[str] = None, - use_cache: bool = True + use_cache: bool = True, + max_retries: int = 3 # [新增] 最大重试次数参数 ) -> pd.DataFrame: """获取加密货币对的OHLCV数据 @@ -128,19 +130,30 @@ class BinanceDataFetcher: print(f"获取 {symbol} {timeframe} 数据,时间范围:{start_dt.date()} 至 {end_dt.date()}...") - # 获取K线数据 - try: - klines = self.client.get_historical_klines( - symbol=pair, - interval=interval, - start_str=str(int(start_dt.timestamp() * 1000)), - end_str=str(int(end_dt.timestamp() * 1000)) - ) - except Exception as e: - if not df.empty: - print(f"⚠ API请求失败 ({e}),返回数据库现有数据") - return df - raise e + klines = [] + for attempt in range(max_retries): + try: + klines = self.client.get_historical_klines( + symbol=pair, + interval=interval, + start_str=str(int(start_dt.timestamp() * 1000)), + end_str=str(int(end_dt.timestamp() * 1000)) + ) + # 如果成功获取,跳出循环 + break + except Exception as e: + # 如果是最后一次尝试,且依然失败 + if attempt == max_retries - 1: + print(f"❌ 第 {attempt + 1} 次尝试失败,已达到最大重试次数。错误: {e}") + if not df.empty: + print(f"⚠ API请求最终失败,返回数据库现有数据") + return df + raise e # 如果没有缓存数据,抛出异常 + + # 计算等待时间 (指数退避: 2s, 4s, 8s...) + wait_time = 2 * (2 ** attempt) + print(f"⚠ 请求失败 (尝试 {attempt + 1}/{max_retries}),{wait_time}秒后重试... 错误: {e}") + time.sleep(wait_time) if not klines: if not df.empty: