从subprocess.Popen.stdout读取多行

4 投票
2 回答
4598 浏览
提问于 2025-04-16 05:13

我修改了Fred Lundh的Python标准库的源代码。原来的代码是用popen2来和子进程沟通,但我把它改成了用subprocess.Popen(),具体如下。

import subprocess
import string

class Chess:
    "Interface class for chesstool-compatible programs"

    def __init__(self, engine = "/opt/local/bin/gnuchess"):
        proc=subprocess.Popen([engine],stdin=subprocess.PIPE,stdout=subprocess.PIPE)
        self.fin, self.fout = proc.stdin, proc.stdout

        s = self.fout.readline() <--
        print s
        if not s.startswith("GNU Chess"):
            raise IOError, "incompatible chess program"

    def move(self, move):
        ...
        my = self.fout.readline() <--
        ...

    def quit(self):
        self.fin.write("quit\n")
        self.fin.flush()

g = Chess()
print g.move("a2a4")
print g.move("b2b3")
g.quit()

看起来运行得还不错,但gnuchess会打印出多行信息,而用self.fout.readline()只显示一行。

Thinking...
... 
R N B Q K B N R 

我该怎么才能获取多行信息呢?readlines()这个方法似乎不管用。

补充说明

我测试了movieyoda的代码,但它不管用。我觉得只有readline()应该能工作,而readlines()和read()不行,因为后者不知道什么时候该停止读取,只有readline()能做到这一点。

2 个回答

0

我会直接读取它输出的内容,等到这个进程结束时,子进程模块会帮你处理后面的清理工作。你可以这样做 -

l = list()
while True:
    data = proc.stdout.read(4096)
    if not data:
        break
    l.append(data)
file_data = ''.join(l)

这些都是用来替代 self.fout.readline() 的方法。我还没试过,但应该可以处理多行内容。

2

要和gnuchess进行互动,我会使用pexpect这个工具。

import pexpect
import sys
game = pexpect.spawn('/usr/games/gnuchess')
# Echo output to stdout
game.logfile = sys.stdout
game.expect('White')
game.sendline('a2a4')
game.expect('White')
game.sendline('b2b3')
game.expect('White')
game.sendline('quit')

撰写回答