[英]Using set input for stdin based on output from stdout with python subprocess
[英]`stdout` is empty when passing data to `stdin` via `subprocess`, but contains the expected output when input is entered manually?
所以我正在努力嘗試從 Leela Chess Zero 引擎接收國際象棋移動數據。 我已經完成了所有 UI 和后端的其他部分,這是我需要實現的最后一件事。 不幸的是,我似乎高估了 Python 中子處理的簡單程度......
為了解釋更多背景,我需要做的就是:
lc0.exe
。 我處理得很好。position startpos e2e4 e7e5 e1e2
, go nodes 100
,按順序通過標准輸入quit
。 根據我可以通過 stderr 衡量的內容,這似乎也可以正常工作。這是我到目前為止嘗試過的事情:
>>> from subprocess import Popen, PIPE, STDOUT
>>> p = Popen(['lc0'], stdout=PIPE, stdin=PIPE, stderr=PIPE)
>>> stdout_data = p.communicate(input=b'position startpos e2e4 e7e5 e1e2\ngo nodes 100\nquit')[0]
>>> stdout_data
b''
我得到一個空字節字符串。 然后我嘗試了另一種方法作為測試:
>>> import subprocess
>>> subprocess.check_output(['lc0'], stderr=PIPE) #the following 3 lines is me typing into stdin
position startpos e2e4 e7e5 e1e2
go nodes 100
quit
b'info depth 1 seldepth 2 time 4081 nodes 4 score cp 12 nps 133 tbhits 0 pv e2e4 c7c5\r\ninfo depth 2 seldepth 3 time 4116 nodes 11 score cp 13 nps 166 tbhits 0 pv e2e4 c7c5 g1f3\r\ninfo depth 3 seldepth 4 time 4151 nodes 25 score cp 13 nps 247 tbhits 0 pv e2e4 c7c5 g1f3 e7e6\r\ninfo depth 3 seldepth 5 time 4218 nodes 68 score cp 13 nps 407 tbhits 0 pv e2e4 c7c5 b1c3 b8c6 g1e2\r\ninfo depth 4 seldepth 6 time 4312 nodes 134 score cp 13 nps 513 tbhits 0 pv e2e4 c7c5 b1c3 b8c6 g1f3 e7e5\r\nbestmove e2e4 ponder c7c5\r\n'
尤里卡。 我從標准輸出收到了正確的 output: 現在是時候以編程方式進行操作了:
>>> subprocess.check_output(['lc0'], stderr=PIPE, input=b'position startpos e2e4 e7e5 e1e2\ngo nodes 100\nquit')
b''
混蛋? 這里發生了什么? 我可以通過刪除stderr=PIPE
參數來確認所有命令顯然確實是由引擎運行的,但是當一切都說完之后,當我以編程方式傳遞命令時,stdout 是空的。 我也嘗試過使用subprocess.stdin.write()
得到相同的結果。
經過大量挖掘,我發現pexpect
可能更適合這個用例。 我安裝了pip install wexpect
and lo' 並且看:
>>> from wexpect import spawn
>>> child = spawn("lc0")
...
是的,它只是掛起。 打破 ^C 給了我異常pywintypes.error: (2, 'CreateFile', 'The system cannot find the file specified.')
,所以我可以理解地對使用pexpect
而不是subprocess
不太自信,因為我似乎更接近后者的解決方案。
無論如何,我確信我以某種方式濫用subprocess
,但我到底做錯了什么? 為什么我在手動通過stdin
傳遞命令時正確接收stdout
,但在使用input=
參數時卻沒有?
我們可以使用 stdin.write() 一次向引擎發送一個命令。 還正確發送 position 命令, moves
如下: position startpos moves m1, m2...
安全退出引擎並正確終止進程。
from subprocess import Popen, PIPE, STDOUT, TimeoutExpired
def ecommand(p, comm):
p.stdin.write(f'{comm}\n')
def analyze(efile):
bestmove = '0000'
p = Popen([efile], stdout=PIPE, stdin=PIPE, stderr=STDOUT, bufsize=0, text=True) # stderr=STDOUT, also send stderr to stdout to see everything in stdout
ecommand(p, 'position startpos moves e2e4 e7e5 e1e2')
ecommand(p, 'go nodes 3000')
for line in iter(p.stdout.readline, ''): # read each line of engine output as replies from our command
line = line.strip()
print(line)
if line.startswith('bestmove'): # exit the loop when we get the engine bestmove
bestmove = line.split()[1].strip()
break
ecommand(p, 'quit') # properly quit the engine
# Make sure process 'p' is terminated (if not terminated for some reason) as we already sent the quit command.
try:
p.communicate(timeout=5)
except TimeoutExpired: # If timeout has expired and process is still not terminated.
p.kill()
p.communicate()
return bestmove
efile = 'E:\\Chess_Engines\\Lc0\\lc0-v0.28.0-windows-cpu-openblas\\lc0.exe'
bestmove = analyze(efile)
print(f'best move: {bestmove}')
_
| _ | |
|_ |_ |_| v0.28.0 built Aug 25 2021
Detected 4 core(s) and 8 thread(s) in 1 group(s).
...
info depth 1 seldepth 2 time 181 nodes 2 score cp 88 nps 142 tbhits 0 pv g8f6 d2d3
info depth 2 seldepth 3 time 200 nodes 3 score cp 89 nps 90 tbhits 0 pv g8f6 d2d3 d7d5
info depth 2 seldepth 4 time 236 nodes 5 score cp 93 nps 72 tbhits 0 pv g8f6 b1c3 b8c6 d2d3
info depth 3 seldepth 5 time 305 nodes 15 score cp 99 nps 107 tbhits 0 pv g8f6 d2d3 d7d5 b1c3 d5d4
info depth 3 seldepth 6 time 368 nodes 23 score cp 96 nps 114 tbhits 0 pv g8f6 d2d3 d7d5 b1c3 d5d4 c3b1
info depth 4 seldepth 7 time 466 nodes 34 score cp 105 nps 113 tbhits 0 pv g8f6 d2d3 d7d5 b1c3 d5d4 c3b1 b8c6
info depth 4 seldepth 8 time 561 nodes 55 score cp 106 nps 139 tbhits 0 pv g8f6 d2d3 d7d5 b1c3 d5d4 c3b1 b8c6
info depth 5 seldepth 8 time 871 nodes 105 score cp 109 nps 149 tbhits 0 pv g8f6 d2d3 d7d5 b1c3 b8c6 c1g5 c8e6 g1f3
info depth 5 seldepth 9 time 965 nodes 119 score cp 111 nps 149 tbhits 0 pv g8f6 d2d3 d7d5 b1c3 b8c6 c1g5 c8e6 g1f3
info depth 5 seldepth 10 time 1327 nodes 179 score cp 109 nps 154 tbhits 0 pv g8f6 d2d3 d7d5 b1c3 b8c6 c1g5 c8e6 g1f3 d5d4
info depth 5 seldepth 11 time 1444 nodes 206 score cp 110 nps 161 tbhits 0 pv g8f6 d2d3 d7d5 b1c3 b8c6 c1g5 c8e6 g1f3 d5d4 c3b1
info depth 5 seldepth 12 time 1621 nodes 240 score cp 110 nps 165 tbhits 0 pv g8f6 d2d3 d7d5 b1c3 b8c6 c1g5 c8e6 g1f3 d5d4 c3b1
info depth 6 seldepth 12 time 2126 nodes 331 score cp 112 nps 168 tbhits 0 pv g8f6 d2d3 d7d5 b1c3 b8c6 c1g5 c8e6 g1f3 d5d4 c3b1
info depth 6 seldepth 13 time 2582 nodes 430 score cp 111 nps 178 tbhits 0 pv g8f6 d2d3 d7d5 b1c3 b8c6 c1g5 c8e6 g1f3 d5d4 c3b1
info depth 6 seldepth 14 time 5050 nodes 1037 score cp 111 nps 212 tbhits 0 pv g8f6 d2d3 d7d5 b1c3 b8c6 c1g5 c8e6 e4d5 c6d4 e2d2 e6d5
info depth 7 seldepth 14 time 5569 nodes 1161 score cp 111 nps 214 tbhits 0 pv g8f6 d2d3 d7d5 b1c3 b8c6 c1g5 c8e6 e4d5 c6d4 e2d2 e6d5
info depth 7 seldepth 15 time 8385 nodes 1938 score cp 109 nps 235 tbhits 0 pv g8f6 d2d3 d7d5 b1c3 b8c6 c1g5 c6d4 e2e1 c7c6 g1f3 d8b6 a1b1 c8e6 f3e5
info depth 7 seldepth 15 time 8642 nodes 2007 score cp 109 nps 236 tbhits 0 pv g8f6 d2d3 d7d5 b1c3 b8c6 c1g5 c6d4 e2e1 c7c6 g1f3 d8b6 a1b1 c8e6 f3e5
bestmove g8f6 ponder d2d3
best move: g8f6
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.