通过“subprocess”将数据传递给“stdin”时,“stdout”为空,但包含手动输入时的预期输出?

问题描述

所以我正在尝试从 Leela Chess Zero 引擎接收国际象棋移动数据。我已经完成了所有 UI 和后端的其他部分,这是我需要实现的最后一件事。不幸的是,我似乎高估了 Python 中子处理的简单程度...

为了解释更多背景,我需要做的就是:

  1. 在本地目录中调用/运行 lc0.exe。我做得很好。
  2. 按顺序通过标准输入传递命令 position startpos e2e4 e7e5 e1e2go nodes 100quit。根据我可以通过 stderr 衡量的内容,这似乎也能正常工作。
  3. 接收/读取标准输出。这就是我被困的地方。

这是我迄今为止尝试过的事情:

>>> 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'

尤里卡!我从标准输出收到了正确的输出。现在是时候以编程方式执行此操作了:

>>> 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 并且你看:

>>> from wexpect import spawn
>>> child = spawn("lc0")

...

是的,它只是挂起。打破 ^C 给了我例外 pywintypes.error: (2,'CreateFile','The system cannot find the file specified.'),所以我可以理解地对使用 pexpect 而不是 subprocess 感到不太自信,因为我似乎更接近使用后者的解决方案。

无论如何,我确信我以某种方式误用了 subprocess,但我到底做错了什么?为什么我在手动通过 stdout 传递命令时可以正确接收 stdin,而在使用 input= 参数时却没有?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)