英文:
Communicating with console apps
问题
我是一个初学者。我尝试使用Go语言的exec
包与一个国际象棋引擎进行通信,但它要求我关闭标准输入(stdin)。我希望能够与引擎建立对话。
请问我该如何在Go语言中实现这个功能?
以下是一个Python实现的通信示例,非常直观,可以在https://stackoverflow.com/questions/12341882/how-to-communicate-with-a-chess-engine-in-python找到:
import subprocess, time
engine = subprocess.Popen(
'stockfish-x64.exe',
universal_newlines=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
)
def put(command):
print('\nyou:\n\t'+command)
engine.stdin.write(command+'\n')
def get():
# using the 'isready' command (engine has to answer 'readyok')
# to indicate current last line of stdout
engine.stdin.write('isready\n')
print('\nengine:')
while True:
text = engine.stdout.readline().strip()
if text == 'readyok':
break
if text !='':
print('\t'+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')
为了简化问题,考虑以下Go语言代码:
package main
import (
"bytes"
"fmt"
"io"
"os/exec"
)
func main() {
cmd := exec.Command("stockfish")
stdin, _ := cmd.StdinPipe()
io.Copy(stdin, bytes.NewBufferString("isready\n"))
var out bytes.Buffer
cmd.Stdout = &out
cmd.Run()
fmt.Printf(out.String())
}
这个程序在没有打印任何内容的情况下等待。但是当我关闭标准输入(stdin)时,程序会打印结果,但关闭标准输入(stdin)会阻碍引擎和Go程序之间的通信。
解决方案如下:
package main
import (
"bytes"
"fmt"
"io"
"os/exec"
"time"
)
func main() {
cmd := exec.Command("stockfish")
stdin, _ := cmd.StdinPipe()
io.Copy(stdin, bytes.NewBufferString("isready\n"))
var out bytes.Buffer
cmd.Stdout = &out
cmd.Start()
time.Sleep(1000 * time.Millisecond)
fmt.Printf(out.String())
}
英文:
I am a beginner. I have tried to communicate to a chess engine with go's exec
package, but it requires me to close the stdin. What I wish to do is to establish a dialogue with the engine.
How do I do that with go?
This is the python implementation of the communication which is pretty much straight forward, can be found at https://stackoverflow.com/questions/12341882/how-to-communicate-with-a-chess-engine-in-python
import subprocess, time
engine = subprocess.Popen(
'stockfish-x64.exe',
universal_newlines=True,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
)
def put(command):
print('\nyou:\n\t'+command)
engine.stdin.write(command+'\n')
def get():
# using the 'isready' command (engine has to answer 'readyok')
# to indicate current last line of stdout
engine.stdin.write('isready\n')
print('\nengine:')
while True:
text = engine.stdout.readline().strip()
if text == 'readyok':
break
if text !='':
print('\t'+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')
For simplicity consider this in go:
package main
import (
"bytes"
"fmt"
"io"
"os/exec"
)
func main() {
cmd := exec.Command("stockfish")
stdin, _ := cmd.StdinPipe()
io.Copy(stdin, bytes.NewBufferString("isready\n"))
var out bytes.Buffer
cmd.Stdout = &out
cmd.Run()
fmt.Printf(out.String())
}
The program waits without printing anything. But when I close the stdin the program prints the result, but closing the stdin hinders communication between the engine and go program.
The solution:
package main
import (
"bytes"
"fmt"
"io"
"os/exec"
"time"
)
func main() {
cmd := exec.Command("stockfish")
stdin, _ := cmd.StdinPipe()
io.Copy(stdin, bytes.NewBufferString("isready\n"))
var out bytes.Buffer
cmd.Stdout = &out
cmd.Start()
time.Sleep(1000 * time.Millisecond)
fmt.Printf(out.String())
}
答案1
得分: 2
你仍然可以使用exec.Command
来实现这个功能,然后使用Cmd方法cmd.StdinPipe()
、cmd.StdoutPipe()
和cmd.Start()
。
文档中的exec.Cmd.StdoutPipe示例应该能帮助你入门:http://golang.org/pkg/os/exec/#Cmd.StdoutPipe
但在你的情况下,你需要在一个循环中读取和写入管道。我想你的架构会像这样,在一个goroutine中的循环中,通过通道将命令传递给你的其他代码。
英文:
You should still be able to do this with exec.Command
and then with the Cmd methods cmd.StdinPipe()
, cmd.StdoutPipe()
, and cmd.Start()
The example in the docs for exec.Cmd.StdoutPipe should be able to get you started: http://golang.org/pkg/os/exec/#Cmd.StdoutPipe
But in your case, you'd be doing reads and writes from the pipes in a loop. I'd imagine your architecture will look like this loop in a goroutine, passing commands to-and-fro the rest of your code via channels.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论