diff --git a/deploy/profile-scripts/batch_reassess.py b/deploy/profile-scripts/batch_reassess.py index 69a1cc6b..739e3313 100644 --- a/deploy/profile-scripts/batch_reassess.py +++ b/deploy/profile-scripts/batch_reassess.py @@ -25,7 +25,7 @@ STALE_HOURS = 20 # 分析超过20小时视为过期,需要重评 def has_llm_analysis(code): """检查是否为LLM生成的12维分析(>500字)""" - conn = sqlite3.connect(DB) + conn = sqlite3.connect(DB, timeout=30) r = conn.execute("SELECT LENGTH(full_analysis) FROM holding_strategies WHERE code=? AND status='active'", (code,)).fetchone() conn.close() return r and r[0] and r[0] > 500 @@ -37,7 +37,6 @@ def in_cooldown(code): if FORCE_REASSESS: return False conn = sqlite3.connect(DB, timeout=30) - conn.execute("PRAGMA busy_timeout=30000") r = conn.execute("SELECT reassessed_at FROM holding_strategies WHERE code=? AND status='active'", (code,)).fetchone() conn.close() if not r or not r[0]: @@ -51,7 +50,7 @@ def in_cooldown(code): def analysis_stale(code, force_today=False): """分析是否过期(>STALE_HOURS 或 force_today 时今早4点前未重评)""" - conn = sqlite3.connect(DB) + conn = sqlite3.connect(DB, timeout=30) r = conn.execute("SELECT reassessed_at FROM holding_strategies WHERE code=? AND status='active'", (code,)).fetchone() conn.close() if not r or not r[0]: @@ -69,7 +68,6 @@ def get_portfolio(): """从 portfolio_summary 读实时现金/总资产(不再硬编码)""" try: conn = sqlite3.connect(DB, timeout=30) - conn.execute("PRAGMA busy_timeout=30000") r = conn.execute("SELECT cash, total_assets FROM portfolio_summary WHERE id=1").fetchone() conn.close() if r and r[1]: @@ -83,7 +81,7 @@ def collect_data(code): data = {"code": code} # 从DB读策略(含 full_analysis / changelog_json / position_advice) - conn = sqlite3.connect(DB) + conn = sqlite3.connect(DB, timeout=30) r = conn.execute("SELECT name, entry_low, entry_high, stop_loss, take_profit, timing_signal, action, rr_ratio, tech_snapshot, sector_context, stock_category, full_analysis, changelog_json, reassessed_at, position_advice FROM holding_strategies WHERE code=? AND status='active'", (code,)).fetchone() if r: data["name"] = r[0] @@ -136,7 +134,7 @@ def collect_data(code): if (not _sector_ctx) or _sector_ctx.startswith('大盘上涨比') or len(_sector_ctx) < 4: _resolved = "" try: - _sdb = sqlite3.connect(DB) + _sdb = sqlite3.connect(DB, timeout=30) _sr = _sdb.execute("SELECT sector_name FROM stock_sectors WHERE code=? LIMIT 1", (code,)).fetchone() _sdb.close() if _sr and _sr[0]: @@ -147,7 +145,7 @@ def collect_data(code): data['sector_context'] = _sector_ctx # 大盘 try: - conn = sqlite3.connect(DB) + conn = sqlite3.connect(DB, timeout=30) mr = conn.execute("SELECT structure FROM macro_context_log ORDER BY id DESC LIMIT 1").fetchone() if mr and mr[0]: s = json.loads(mr[0]) @@ -296,7 +294,7 @@ def build_prompt(data): _rotation_context = "" if not data.get('held'): try: - _rc = sqlite3.connect(DB) + _rc = sqlite3.connect(DB, timeout=30) _weak = _rc.execute(""" SELECT hs.code, hs.name, hs.timing_signal, h.position_pct, h.cost FROM holding_strategies hs @@ -505,7 +503,8 @@ def save_result(code, full_text, parsed, ta_levels=None): if not (full_text or "").strip(): print(f" \u274c 拒绝写入空分析(LLM输出为空,保护已有数据)") return - conn = sqlite3.connect(DB) + conn = sqlite3.connect(DB, timeout=30) + conn.execute("PRAGMA busy_timeout=30000") now = datetime.now().isoformat() # ── 修改前快照 ── @@ -689,7 +688,6 @@ def main(): # 按类型筛选 active 策略 type_map = {"holding": "持仓策略", "watchlist": "自选策略"} conn = sqlite3.connect(DB, timeout=30) - conn.execute("PRAGMA busy_timeout=30000") if dtype in type_map: rows = conn.execute( "SELECT code FROM holding_strategies WHERE status='active' AND decision_type=? ORDER BY code",