Files
sanguo_vnpy_v2/scripts/data_platform/bs_daily_main.py
T

72 lines
2.8 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""bs_daily_main.py — sanguo-bs-daily (VPS schtask 18:05) 单入口: 串行 bs_eod → bs_fundamentals.
2026-08-20 数据任务重组(用户拍板「bs 每天」合并): 根治当日撞点 —— bs_eod 主循环后
新增指数段后单日跑 5~5.5h(ETA 23:00+), 与旧 sanguo-bs-fund 23:05 重叠 = 同 IP 双
baostock 连接 = 封禁红线(6-24h)。合并进同一 schtask 后两腿先后子进程, 连接天然互斥:
leg1 进程退出(finally bs.logout + 进程消亡)连接才彻底释放, leg2 才 login。
编排原则(两脚本幂等/断点/配额逻辑原样复用零改动):
- 只做顺序 + 退出码透传 + 时间线日志([BS-DAILY] 腿起止行, 供验收"eod logout 之后
fund 才 login"的直接证据)
- leg2 无条件跑: leg1 无论成败, 进程退出即连接释放; fund 是独立作业(自带登录重试/
日预算), leg1 致命不该连坐饿死当日财务回灌
- 退出码语义沿用两脚本: 0=完成/让路, 1=致命, 2=登录失败, 3=日预算/防线 graceful stop
(3 是"按预算收工", 不算失败不上报); 任务级退出码 = 第一个非 OK 腿的码
配额(单 IP 48000/天铁律): wrapper 传 BS_DAILY_LIMIT=15000 收紧 eod 病态重试上限
(常态 ~11.1k 不受影响) + fund 自有 DAILY_CAP=30000 → 最坏 45.1k < 48k。
"""
import argparse
import logging
import subprocess
import sys
import time
from pathlib import Path
HERE = Path(__file__).resolve().parent
LEGS = (
("bs_eod", HERE / "bs_eod.py"),
("bs_fund", HERE / "bs_fundamentals.py"),
)
OK_CODES = {0, 3} # 3=按预算 graceful stop, 属正常收工
logging.basicConfig(level=logging.INFO,
format="%(asctime)s %(levelname)s %(message)s",
handlers=[logging.StreamHandler(sys.stdout)])
log = logging.getLogger(__name__)
def run_leg(name, script):
t0 = time.time()
log.info("[BS-DAILY] leg=%s start script=%s", name, script.name)
rc = subprocess.run(
[sys.executable, "-X", "utf8", str(script)]).returncode
log.info("[BS-DAILY] leg=%s exit=%d 耗时%.0fs", name, rc, time.time() - t0)
return rc
def main(argv=None):
ap = argparse.ArgumentParser()
ap.add_argument("--smoke", action="store_true",
help="只验 schtask→wrapper→python 链路可达, 两腿不跑(零配额)")
args = ap.parse_args(argv)
if args.smoke:
log.info("[BS-DAILY] smoke ok 编排入口可达")
return 0
rc1 = run_leg(*LEGS[0])
if rc1 not in OK_CODES:
log.warning("[BS-DAILY] leg1 非常规退出 %d —— 连接已随进程释放, "
"fund 独立作业照跑", rc1)
rc2 = run_leg(*LEGS[1])
if rc1 not in OK_CODES:
return rc1
return 0 if rc2 in OK_CODES else rc2
if __name__ == "__main__":
sys.exit(main())