ZhuLinsen/daily_stock_analysis · error · DataFetchError

[{self.name}] {stock_code}: {error_reason}

Error message

[{self.name}] {stock_code}: {error_reason}

What it means

The catch-all wrapper in BaseFetcher.get_daily_data: any exception escaping the pipeline (fetch, _normalize_data, _clean_data, _calculate_indicators) or re-raised from steps 1-3 is summarized via summarize_exception and re-raised as DataFetchError with the original as __cause__. The message '获取失败' with error_type/reason in the preceding log line is the diagnostic.

Source

Thrown at data_provider/base.py:528

            
            # Step 4: 计算技术指标
            df = self._calculate_indicators(df)

            elapsed = time.time() - request_start
            logger.info(
                f"[{self.name}] {stock_code} 获取成功: 范围={start_date} ~ {end_date}, "
                f"rows={len(df)}, elapsed={elapsed:.2f}s"
            )
            return df
            
        except Exception as e:
            elapsed = time.time() - request_start
            error_type, error_reason = summarize_exception(e)
            logger.error(
                f"[{self.name}] {stock_code} 获取失败: 范围={start_date} ~ {end_date}, "
                f"error_type={error_type}, elapsed={elapsed:.2f}s, reason={error_reason}"
            )
            raise DataFetchError(f"[{self.name}] {stock_code}: {error_reason}") from e
    
    def _clean_data(self, df: pd.DataFrame) -> pd.DataFrame:
        """
        数据清洗
        
        处理:
        1. 确保日期列格式正确
        2. 数值类型转换
        3. 去除空值行
        4. 按日期排序
        """
        df = df.copy()
        
        # 确保日期列为 datetime 类型
        if 'date' in df.columns:
            df['date'] = pd.to_datetime(df['date'])
        
        # 数值列类型转换

View on GitHub (pinned to 5159bd72e8)

Solutions

  1. Read the 'error_type=..., reason=...' in the logged '获取失败' line immediately before the raise — it names the root exception, not this wrapper.
  2. Reproduce with a direct call to the failing step (e.g. fetcher._normalize_data(raw_df, code)) on the logged date range to isolate which pipeline stage threw.
  3. Fix the root cause in the responsible step (column mapping, dtype coercion, indicator guard) rather than catching DataFetchError at the call site.
Defensive patterns

Strategy: fallback

Try / catch

try:
    df = manager.get_daily_data(code, ...)
except DataFetchError as e:
    logger.warning('daily fetch failed for %s: %s', code, e)
    df = load_cached_daily(code)  # or skip / use next market source

Prevention

When it happens

Trigger: Any unhandled exception inside _fetch_raw_data, _normalize_data, _clean_data, or _calculate_indicators: schema drift (missing columns), type coercion failures, indicator math errors on degenerate data (single row, all-NaN), or a lower-level DataFetchError/RateLimitError being re-wrapped.

Common situations: Provider renames/drops a column so normalization raises KeyError; technical indicator division by zero on flat data; network errors from the fetch step bubbling up with the elapsed-time context attached.

Related errors


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