|
|
@@ -125,14 +125,27 @@ def analyze(cfg, input_path=None, window=None, steps=None, bands='ALL'):
|
|
|
env['M5_WINDOWS'] = ','.join(wins)
|
|
|
env['SCAN_BANDS'] = bands
|
|
|
want = set(steps or ['oem_scan', 'energy_share', 'model_run', 'fusion', 'report', 'kb'])
|
|
|
+ # ★ 2026-09-17: 缺脚本要给"人看得懂、且知道去哪儿要料"的错, 而不是让 python 抛一句
|
|
|
+ # `can't open file 'scripts/rudong_model_run.py'`(实测就是这句 —— 现场看到它没法判断
|
|
|
+ # 这是"包缺件"还是"我敲错了")。四步脚本属振动线分支产物, 未随包; 缺了就指名要说清楚。
|
|
|
+ def _step(name: str, script: str):
|
|
|
+ p = ROOT / 'scripts' / script
|
|
|
+ if not p.is_file():
|
|
|
+ raise RuntimeError(
|
|
|
+ f'六层链的 {name} 步脚本未随包: {p.relative_to(ROOT).as_posix()}(振动线分支产物)。'
|
|
|
+ f'调用约定见 docs/振动六层链_接口规格与缺口_v0.1.md §1, 取料单见 docs/向振动线取料单_v0.1.md; '
|
|
|
+ f'自查: python scripts/chain_gap_check.py。'
|
|
|
+ f'(本包已逆向实现 fusion 步的一件产物: scripts/rudong_fusion_run.py 可重出 fleet_scalar_z)')
|
|
|
+ return [PY, str(p)]
|
|
|
+
|
|
|
if 'oem_scan' in want:
|
|
|
- _run('oem_scan', [PY, str(ROOT / 'scripts/rudong_tcm_oem_scan.py')], env, log)
|
|
|
+ _run('oem_scan', _step('oem_scan', 'rudong_tcm_oem_scan.py'), env, log)
|
|
|
if 'energy_share' in want:
|
|
|
- _run('energy_share', [PY, str(ROOT / 'scripts/rudong_line_energy_share.py')], env, log)
|
|
|
+ _run('energy_share', _step('energy_share', 'rudong_line_energy_share.py'), env, log)
|
|
|
if 'model_run' in want:
|
|
|
- _run('model_run', [PY, str(ROOT / 'scripts/rudong_model_run.py')], env, log)
|
|
|
+ _run('model_run', _step('model_run', 'rudong_model_run.py'), env, log)
|
|
|
if 'fusion' in want:
|
|
|
- _run('fusion', [PY, str(ROOT / 'scripts/rudong_fusion_run.py')], env, log)
|
|
|
+ _run('fusion', _step('fusion', 'rudong_fusion_run.py'), env, log)
|
|
|
if 'report' in want:
|
|
|
# 标量缓存按窗集合命名, 新窗自动失效; 谱元数据进程内缓存由新进程重建
|
|
|
_run('report', [PY, str(ROOT / 'scripts/windcms.py'), 'report', '--farm', cfg.get('key', 'rudong')], env, log)
|
|
|
@@ -153,4 +166,12 @@ def analyze(cfg, input_path=None, window=None, steps=None, bands='ALL'):
|
|
|
with open(logp, 'w', encoding='utf-8', newline='\n') as f:
|
|
|
json.dump(summary, f, ensure_ascii=False, indent=1)
|
|
|
print(f'analyze {status}: {summary["seconds"]}s → {logp}', flush=True)
|
|
|
+ if status != 'ok':
|
|
|
+ # ★ 2026-09-17: 失败时把**原因**打到控制台, 而不是只留一句 "analyze failed" 让人去翻 JSON。
|
|
|
+ # 实测场景: 四步脚本未随包时, 原来只在日志里能看到 python 的 FileNotFoundError,
|
|
|
+ # 现场看到的是"重算失败"四个字, 无从判断是包缺件还是操作有误。
|
|
|
+ bad = [s for s in log if s.get('step') == 'FAILED'] + [s for s in log if s.get('rc') not in (0, None)]
|
|
|
+ for s in bad[:2]:
|
|
|
+ print(' [X] ' + str(s.get('step')) + ': ' + str(s.get('tail', '')).strip()[:400], flush=True)
|
|
|
+ print(f' 详情: {logp}', flush=True)
|
|
|
return summary
|