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
- Parse the joined per-source messages to identify whether failures are rate limits (slow down / back off) vs parse errors (upgrade akshare/efinance).
- Configure a key-based fallback source (e.g. TUSHARE_TOKEN) so the chain has a non-free-tier option.
- 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
- Rate-limit A-share batch loops to avoid tripping every free source at once.
- Provide TUSHARE_TOKEN (or another key source) as a non-Eastmoney fallback.
- Run the network-smoke suite before scheduled jobs to detect all-sources-failed early.
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
- {market_label} {stock_code} 获取失败: {errors joined by newline}
- Akshare 所有渠道获取失败: {last_error}
- Akshare(EM) 可能被限流: {e}
- Akshare 可能被限流: {e}
- [{self.name}] 未获取到 {stock_code} 的数据
AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15).
Data as JSON: /api/errors/4682413d12d93908.
Report an issue: GitHub.