Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
556 views
in Technique[技术] by (71.8m points)

process - How to Communicate with a Chess engine in Python?

on win 7 i can communicate with a chess engine via commandline. Small Example Session with Stockfish on Win 7:

C:
unStockfish>stockfish-x64.exe
Stockfish 2.2.2 JA SSE42 by Tord Romstad, Marco Costalba and Joona Kiiski
quit

C:
unStockfish>

The first line was output by the engine and the 'quit' was what i typed to quit the engine (There are other things i can do, but thats clear to me).

Now i want to communicate with that engine from python:

import subprocess
engine = subprocess.Popen(
    'stockfish-x64.exe',
    stdin=subprocess.PIPE,
    stdout=subprocess.PIPE,
)
for line in engine.stdout:
    print(line.strip())
engine.stdin.write('quit
')

and i get

C:
unStockfish>communicate.py
b'Stockfish 2.2.2 JA SSE42 by Tord Romstad, Marco Costalba and Joona Kiiski'

but it doesnt quit the engine (no C: unStockfish> prompt), it keeps waiting for input. I have to close the window by hand. It seems not to get my quit message (last line of the python script) written to stdin.

In other words i can read from stdout but when i write to stdin nothing happens.

What am i doing wrong and how to do it right?


Edit: ok, thanks to larsmans′ help i solved it:

Example Python script:

import subprocess, time

engine = subprocess.Popen(
    'stockfish-x64.exe',
    universal_newlines=True,
    stdin=subprocess.PIPE,
    stdout=subprocess.PIPE,
    bufsize=1,
)

def put(command):
    print('
you:
'+command)
    engine.stdin.write(command+'
')
    
def get():
    # using the 'isready' command (engine has to answer 'readyok')
    # to indicate current last line of stdout
    engine.stdin.write('isready
')
    print('
engine:')
    while True:
        text = engine.stdout.readline().strip()
        if text == 'readyok':
            break
        if text !='':
            print(''+text)

get()
put('uci')
get()
put('setoption name Hash value 128')
get()
put('ucinewgame')
get()
put('position startpos moves e2e4 e7e5 f2f4')
get()
put('go infinite')
time.sleep(3)
get()
put('stop')
get()
put('quit')

Output:

C:
unStockfish>1-communicate.py

engine:
        Stockfish 2.2.2 JA SSE42 by Tord Romstad, Marco Costalba and Joona Kiiski

you:
        uci

engine:
        id name Stockfish 2.2.2 JA SSE42
        id author Tord Romstad, Marco Costalba and Joona Kiiski
        option name Use Search Log type check default false
        option name Search Log Filename type string default SearchLog.txt
        ... etc ...
        uciok

you:
        setoption name Hash value 128

engine:

you:
        ucinewgame

engine:

you:
        position startpos moves e2e4 e7e5 f2f4

engine:

you:
        go infinite

engine:
        info depth 1 seldepth 1 score cp 56 nodes 62 nps 1675 time 37 multipv 1 pv e5f4
        info depth 2 seldepth 2 score cp 48 nodes 804 nps 21157 time 38 multipv 1 pv b8c6 g1h3
        info depth 3 seldepth 3 score cp 64 nodes 1409 nps 37078 time 38 multipv 1 pv b8c6 b1c3 e5f4
        ... etc ...

you:
        stop

engine:
        bestmove e5f4 ponder g1f3

you:
        quit

C:
unStockfish>
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You've got a deadlock: the subprocess is waiting for input, while your program is waiting for it to output more lines in

for line in engine.stdout:
    print(line.strip())

This loop only stops when the subprocess closes its stdout.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...