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

lichess-bot中stdin被重定向后如何读取用户输入?

解决lichess-bot重定向stdin后读取用户输入的问题

核心原因

lichess-bot为实现与引擎的UCI通信,会重定向标准输入流,导致input()无法读取终端的用户输入,从而抛出EOFError。

解决方案

1. 直接读取终端设备(推荐)

绕过被重定向的stdin,直接读取终端的原始输入设备,适配Linux/macOS和Windows系统:

import sys
from typing import PlayResult
from chess import Board
from lichess_bot.engine_wrapper import MinimalEngine

class HumanCLI(MinimalEngine):
    def search(self, board: Board, *args) -> PlayResult:
        # 适配不同系统的终端输入设备
        if sys.platform.startswith('win'):
            terminal_input = open('con', 'r')
        else:
            terminal_input = open('/dev/tty', 'r')
        
        while True:
            user_input = terminal_input.readline().strip()
            # 验证走法合法性
            try:
                move = board.parse_uci(user_input)
                if move in board.legal_moves:
                    terminal_input.close()
                    return PlayResult(move, None)
            except ValueError:
                pass
            print("非法走法,请输入UCI格式的合法走法(例如e2e4)")

2. 提前保存原始stdin引用

在lichess-bot重定向stdin之前,保存原始标准输入的文件描述符,后续通过该描述符读取输入:

import sys
import os
from typing import PlayResult
from chess import Board
from lichess_bot.engine_wrapper import MinimalEngine

# 在引擎初始化前保存原始stdin
original_stdin_fd = os.dup(sys.stdin.fileno())
original_stdin = os.fdopen(original_stdin_fd, 'r')

class HumanCLI(MinimalEngine):
    def search(self, board: Board, *args) -> PlayResult:
        while True:
            user_input = original_stdin.readline().strip()
            try:
                move = board.parse_uci(user_input)
                if move in board.legal_moves:
                    return PlayResult(move, None)
            except ValueError:
                pass
            print("非法走法,请输入UCI格式的合法走法(例如e2e4)")

3. 线程后台监听输入(适合复杂交互)

启动独立线程持续监听终端输入,缓存合法走法,search方法直接读取缓存内容:

import sys
import threading
from typing import PlayResult
from chess import Board
from lichess_bot.engine_wrapper import MinimalEngine

class HumanCLI(MinimalEngine):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.cached_move = None
        self.lock = threading.Lock()
        # 后台启动输入监听线程
        input_thread = threading.Thread(target=self._listen_terminal, daemon=True)
        input_thread.start()

    def _listen_terminal(self):
        if sys.platform.startswith('win'):
            terminal_input = open('con', 'r')
        else:
            terminal_input = open('/dev/tty', 'r')
        
        while True:
            user_input = terminal_input.readline().strip()
            with self.lock:
                self.cached_move = user_input

    def search(self, board: Board, *args) -> PlayResult:
        while True:
            with self.lock:
                move_str = self.cached_move
                self.cached_move = None
            if move_str:
                try:
                    move = board.parse_uci(move_str)
                    if move in board.legal_moves:
                        return PlayResult(move, None)
                except ValueError:
                    pass
                print("非法走法,请输入UCI格式的合法走法(例如e2e4)")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 09:35:15