You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

python-chess调用Stockfish分析时意外终止问题求助

批量FEN评估崩溃问题的诊断与解决

问题概述

使用python-chess调用Stockfish对100万个FEN局面进行评估打分,处理到第25430个局面时程序意外终止,报错显示引擎进程因栈溢出崩溃。更换不同引擎后仍在同一位置失败,手动解析大JSON文件未使用JSON库,但排除解析代码导致问题的可能。

复现代码

import chess
import chess.engine

def stockfish_evaluation(board):
  result = engine.analyse(board, chess.engine.Limit(depth=1))
  return result['score'].relative.score(mate_score=10000)

engine = chess.engine.SimpleEngine.popen_uci("/usr/bin/stockfish")
inputf = "lichess-1M.json"
outputf = open("out-1M.data","w")
line_num = sum(1 for _ in open(inputf))
line_count = 0
file = open(inputf)

while True:
  data = ''
  line_buf = 0

  # 按25000行分块读取JSON文件(单行为一个局面,受内存限制)
  for line in file:
    line_count += 1
    line_buf += 1
    print('\r'+f"Processing - {line_count}/{line_num} ({format(line_count/line_num*100,'.2f')}%)  ",end='')
    data += line + '\n'
    if line_buf >= 25000: break

  # 手动提取FEN字段
  n = 0
  s = ''
  isFen = False
  while n < len(data):
    if isFen:
      s += data[n]
      if data[n] == '"':
        isFen = False
        # 调用评估函数并写入结果
        outputf.write(f"{s}: {stockfish_evaluation(chess.Board(s[1:-1]))}\n")
    elif data[n:n+6] == '"fen":':
      isFen = True
      n += 6
      s = '"'
    n += 1

报错信息

<UciProtocol (pid=1014814)>: stderr >> *** stack smashing detected ***: terminated
Traceback (most recent call last):
  File "/home/user/Downloads/chess/test.py", line 33, in <module>
    outputf.write(f"{s}: {stockfish_evaluation(chess.Board(s[1:-1]))}\n")
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/Downloads/chess/test.py", line 5, in stockfish_evaluation
    result = engine.analyse(board, chess.engine.Limit(depth=1))
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/.local/lib/python3.11/site-packages/chess/engine.py", line 2996, in analyse
    return future.result()
           ^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/concurrent/futures/_base.py", line 456, in result
    return self.__get_result()
           ^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/concurrent/futures/_base.py", line 401, in __get_result
    raise self._exception
  File "/usr/lib/python3.11/asyncio/tasks.py", line 452, in wait_for
    return await fut
           ^^^^^^^^^
  File "/home/user/.local/lib/python3.11/site-packages/chess/engine.py", line 1242, in analyse
    await analysis.wait()
  File "/home/user/.local/lib/python3.11/site-packages/chess/engine.py", line 2771, in wait
    return await self._finished
           ^^^^^^^^^^^^^^^^^^^^
chess.engine.EngineTerminatedError: engine process died unexpectedly (exit code: -6)

输出文件检查结果

$ cat out-1M.data | wc -l
25340

解决步骤

1. 定位触发崩溃的FEN

程序在固定位置崩溃,大概率是该位置的FEN存在异常:

  • 修改代码,在处理到第25430行时单独输出对应的FEN字符串。
  • 用chess.Board(fen_str)验证FEN合法性,再手动调用Stockfish评估该FEN,确认是否触发崩溃。

2. 提升程序鲁棒性,避免引擎崩溃终止整体任务

添加异常捕获与引擎重启逻辑,确保单个FEN的问题不中断整个任务:

def stockfish_evaluation(board):
    try:
        result = engine.analyse(board, chess.engine.Limit(depth=1))
        return result['score'].relative.score(mate_score=10000)
    except chess.engine.EngineTerminatedError:
        # 重启引擎
        global engine
        engine.quit()
        engine = chess.engine.SimpleEngine.popen_uci("/usr/bin/stockfish")
        # 重试一次
        try:
            result = engine.analyse(board, chess.engine.Limit(depth=1))
            return result['score'].relative.score(mate_score=10000)
        except Exception as e:
            print(f"Failed evaluating FEN: {board.fen()}, error: {str(e)}")
            return None
    except Exception as e:
        print(f"Error evaluating FEN: {board.fen()}, error: {str(e)}")
        return None

3. 替换手动JSON解析,避免解析错误

手动解析大JSON容易出现边界问题(比如FEN含转义字符),改用流式JSON库ijson,既节省内存又保证解析准确性:

import ijson

# 替换原文件读取与解析逻辑
with open(inputf, 'r') as f:
    for line_count, item in enumerate(ijson.items(f, 'item'), 1):
        fen = item.get('fen')
        if not fen:
            continue
        score = stockfish_evaluation(chess.Board(fen))
        if score is not None:
            outputf.write(f'"{fen}": {score}\n')
        print('\r'+f"Processing - {line_count}/{line_num} ({format(line_count/line_num*100,'.2f')}%)  ",end='')

安装ijson:pip install ijson

4. 引擎参数优化与版本升级

  • 升级Stockfish到最新稳定版,旧版本可能存在特定FEN的处理bug。
  • 限制引擎哈希表大小,降低内存与栈压力:
    engine = chess.engine.SimpleEngine.popen_uci("/usr/bin/stockfish")
    engine.configure({"Hash": 64})  # 设置为64MB,可根据内存情况调整
    

内容的提问来源于stack exchange,提问作者Darwish

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 18:46:03