ZhuLinsen/daily_stock_analysis · error · DataFetchError
Baostock 登录失败: {login_result.error_msg}
Error message
Baostock 登录失败: {login_result.error_msg} What it means
A DataFetchError raised by BaostockFetcher._baostock_session when bs.login() returns a non-zero error_code. Baostock is a free login-based socket service; a failed login means no queries can run, and the context manager aborts before yielding so the logout in finally still runs, preventing connection leaks.
Source
Thrown at data_provider/baostock_fetcher.py:115
确保:
1. 进入上下文时自动登录
2. 退出上下文时自动登出
3. 异常时也能正确登出
使用示例:
with self._baostock_session():
# 在这里执行数据查询
"""
bs = self._get_baostock()
login_result = None
try:
# 登录 Baostock
login_result = bs.login()
if login_result.error_code != '0':
raise DataFetchError(f"Baostock 登录失败: {login_result.error_msg}")
logger.debug("Baostock 登录成功")
yield bs
finally:
# 确保登出,防止连接泄露
try:
logout_result = bs.logout()
if logout_result.error_code == '0':
logger.debug("Baostock 登出成功")
else:
logger.warning(f"Baostock 登出异常: {logout_result.error_msg}")
except Exception as e:
logger.warning(f"Baostock 登出时发生错误: {e}")
def _convert_stock_code(self, stock_code: str) -> str:
"""View on GitHub (pinned to 5159bd72e8)
Solutions
- Retry after a wait — baostock outages are usually transient (check baostock's status/announcements).
- Test standalone: `import baostock as bs; bs.login()` in a REPL to isolate the service vs your code.
- Avoid concurrent baostock sessions (it is a module-level global connection); serialize fetches or use a lock.
- Upgrade the baostock package, then let the manager fall back to Akshare for A-shares.
Example fix
# before
with fetcher._baostock_session() as bs:
... # single attempt, dies on outage
# after
for attempt in range(3):
try:
with fetcher._baostock_session() as bs:
...
break
except DataFetchError as e:
if '登录失败' in str(e):
time.sleep(30 * (attempt + 1))
else:
raise Defensive patterns
Strategy: retry
Validate before calling
import baostock as bs
lg = bs.login()
if lg.error_code != '0':
raise ConnectionError(f'baostock service unavailable: {lg.error_msg}')
bs.logout() Try / catch
for attempt in range(3):
try:
with fetcher._baostock_session() as bs:
df = fetch_under(bs)
break
except DataFetchError as e:
if '登录失败' in str(e) and attempt < 2:
time.sleep(30 * (attempt + 1))
else:
df = akshare_fetcher.fetch(code, start, end)
break Prevention
- Pre-flight baostock login at job start to fail fast during known service outages.
- Serialize baostock usage across threads — its session is a module-level global.
- Schedule A-share jobs outside baostock's maintenance windows.
When it happens
Trigger: baostock.login() failing due to: baostock service under maintenance or offline (common on weekends/holidays), network blocking the socket connection to baostock's server, an outdated/broken baostock package, or too many concurrent sessions holding the single global connection.
Common situations: Baostock's official servers are periodically unavailable — login errors come in waves for all users; running parallel workers where baostock's global singleton session collides; firewall blocking the baostock TCP endpoint in Docker/CI.
Related errors
- Baostock 查询失败: {rs.error_msg}
- Baostock 未查询到 {stock_code} 的数据
- Baostock 获取数据失败: {e}
- BaostockFetcher 不支持港股 {raw_code},请使用 AkshareFetcher
- BaostockFetcher 不支持美股 {stock_code},请使用 AkshareFetcher 或 Yfin
AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15).
Data as JSON: /api/errors/6515a0ff5d8d72cd.
Report an issue: GitHub.