ZhuLinsen/daily_stock_analysis · error · DataFetchError

所有数据源获取 {stock_code} 失败: {errors joined by newline}

Error message

所有数据源获取 {stock_code} 失败:
{errors joined by newline}

What it means

Terminal failure of the generic (A-share/cn) daily-data failover loop in DataFetcherManager: after the last fetcher, the accumulated per-source error messages are joined and raised as DataFetchError. Equivalent to error 144 but for the non-US/HK routing path.

Source

Thrown at data_provider/base.py:1494

                    fallback_to=fallback_to,
                )
                logger.warning(
                    f"[数据源失败 {attempt}/{total_fetchers}] [{fetcher.name}] {stock_code}: "
                    f"error_type={error_type}, reason={error_reason}"
                )
                self._record_daily_source_failure(fetcher, market, error_reason)
                errors.append(error_msg)
                if attempt < total_fetchers:
                    next_fetcher = fetchers[attempt]
                    logger.info(f"[数据源切换] {stock_code}: [{fetcher.name}] -> [{next_fetcher.name}]")
                # 继续尝试下一个数据源
                continue
        
        # 所有数据源都失败
        error_summary = f"所有数据源获取 {stock_code} 失败:\n" + "\n".join(errors)
        elapsed = time.time() - request_start
        logger.error(f"[数据源终止] {stock_code} 获取失败: elapsed={elapsed:.2f}s\n{error_summary}")
        raise DataFetchError(error_summary)
    
    @property
    def available_fetchers(self) -> List[str]:
        """返回可用数据源名称列表"""
        return [f.name for f in self._get_fetchers_snapshot()]
    
    def prefetch_realtime_quotes(self, stock_codes: List[str]) -> int:
        """
        批量预取实时行情数据(在分析开始前调用)
        
        策略:
        1. 检查优先级中是否包含适合预取的数据源(efinance/akshare_em/tushare/tickflow)
        2. 如果不包含,跳过预取(新浪/腾讯是单股票查询,无需预取)
        3. 如果自选股数量 >= 5 且使用可预取数据源,则预取填充缓存
        
        这样做的好处:
        - 使用新浪/腾讯时:每只股票独立查询,无全量拉取问题
        - 使用 efinance/东财/Tushare 时:预取一次,后续缓存命中

View on GitHub (pinned to 5159bd72e8)

Solutions

  1. Parse the joined per-source messages to identify whether failures are rate limits (slow down / back off) vs parse errors (upgrade akshare/efinance).
  2. Configure a key-based fallback source (e.g. TUSHARE_TOKEN) so the chain has a non-free-tier option.
  3. Reduce request frequency or add caching so consecutive failures don't trip the availability circuit breakers.
Defensive patterns

Strategy: fallback

Try / catch

try:
    df = manager.get_daily_data(code, ...)
except DataFetchError as e:
    df = cache.get_daily(code) or raise_analysis_skip(code, str(e))

Prevention

When it happens

Trigger: get_daily_data on an A-share code where every source (efinance, akshare, tushare, ...) fails or is circuit-broken — e.g. Eastmoney anti-bot rate limiting plus missing TUSHARE_TOKEN plus akshare API changes.

Common situations: Scheduled daily jobs hammering Eastmoney until all A-share sources are rate-limited; akshare/efinance version drift breaking response parsing across all free sources at once; sources marked unavailable by the failure recorder after repeated runs.

Related errors


AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15). Data as JSON: /api/errors/4682413d12d93908. Report an issue: GitHub.