ZhuLinsen/daily_stock_analysis · error · DataFetchError
Tushare API 未初始化,请检查 Token 配置
Error message
Tushare API 未初始化,请检查 Token 配置
What it means
DataFetchError raised by TushareFetcher._call_api_with_rate_limit when self._api is None — the Tushare client was never initialized, which happens when the token is missing/empty so the pro API client could not be constructed. It fails before the rate-limit bookkeeping and any remote call.
Source
Thrown at data_provider/tushare_fetcher.py:291
logger.warning(
f"Tushare 达到速率限制 ({self._call_count}/{self.rate_limit_per_minute} 次/分钟),"
f"等待 {sleep_time:.1f} 秒..."
)
time.sleep(sleep_time)
# 重置计数器
self._minute_start = time.time()
self._call_count = 0
# 增加调用计数
self._call_count += 1
logger.debug(f"Tushare 当前分钟调用次数: {self._call_count}/{self.rate_limit_per_minute}")
def _call_api_with_rate_limit(self, method_name: str, **kwargs) -> pd.DataFrame:
"""统一通过速率限制包装 Tushare API 调用。"""
if self._api is None:
raise DataFetchError("Tushare API 未初始化,请检查 Token 配置")
self._check_rate_limit()
method = getattr(self._api, method_name)
return method(**kwargs)
def _get_china_now(self) -> datetime:
"""返回上海时区当前时间,方便测试覆盖跨日刷新逻辑。"""
return datetime.now(ZoneInfo("Asia/Shanghai"))
def _get_trade_dates(self, end_date: Optional[str] = None) -> List[str]:
"""按自然日刷新交易日历缓存,避免服务跨日后继续复用旧日历。"""
if self._api is None:
return []
china_now = self._get_china_now()
requested_end_date = end_date or china_now.strftime("%Y%m%d")
if self.date_list is not None and self._date_list_end == requested_end_date:View on GitHub (pinned to 5159bd72e8)
Solutions
- Set a valid TUSHARE_TOKEN in the runtime environment (and keep .env.example in sync).
- Gate TushareFetcher registration on token presence so unavailable providers are never selected.
- Catch DataFetchError at the manager and fall back to Akshare when Tushare is not configured.
Example fix
# before
df = tushare_fetcher.get_stock_data("600519", start, end) # DataFetchError: not initialized
# after
# .env: TUSHARE_TOKEN=...
import os
if os.getenv("TUSHARE_TOKEN"):
df = tushare_fetcher.get_stock_data("600519", start, end)
else:
df = akshare_fetcher.get_stock_data("600519", start, end) Defensive patterns
Strategy: validation
Validate before calling
import os
tushare_ready = bool(os.getenv("TUSHARE_TOKEN", "").strip()) and tushare_fetcher._api is not None
if not tushare_ready:
df = akshare_fetcher.get_stock_data(code, start, end) Try / catch
try:
df = tushare_fetcher.get_stock_data(code, start, end)
except DataFetchError as e:
if "未初始化" in str(e):
df = akshare_fetcher.get_stock_data(code, start, end)
else:
raise Prevention
- Set TUSHARE_TOKEN wherever the app runs (local, CI, Docker) — not just one shell.
- Only register TushareFetcher when the token is present and initialization succeeds.
- Surface provider init failures at startup logs.
When it happens
Trigger: Calling any Tushare data method (daily, trade_cal, ...) via _call_api_with_rate_limit when TUSHARE_TOKEN is unset/blank or initialization was skipped/failed during fetcher construction.
Common situations: Missing TUSHARE_TOKEN in .env for a new deployment; token defined only in local shell not in Docker/CI; fetcher instantiated before env is loaded; empty-string token passing a truthiness check elsewhere.
Related errors
- Longbridge QuoteContext not available
- TickFlow API key is not configured
- TUSHARE_HTTP_URL 必须以 http:// 或 https:// 开头,当前值为 {url!r}
- [AlphaVantage] API key not configured
- {market_label} {stock_code} 获取失败: 暂无可用数据源
AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15).
Data as JSON: /api/errors/1580d34cd76b1ce4.
Report an issue: GitHub.