【问题标题】:Wrapping an interactive CLI in python在 python 中包装交互式 CLI
【发布时间】:2012-06-09 15:17:12
【问题描述】:

我正在尝试将 gnugo 包装在 python 脚本中。

我已经讨论了 SO 中关于包装 CLI 应用程序 herehere 的其他问题,尽管它们有所帮助,但我无法让我的脚本完全工作。在标准输入的第一次输入之后,该进程似乎被终止了。

脚本如下所示:

import subprocess 

proc = subprocess.Popen(['gnugo', '--mode', 'gtp'], stdout=subprocess.PIPE, stdin=subprocess.PIPE)

c = raw_input('first command: ')

while True:
    r = proc.communicate(c)
    print 'gnugo says: ' + str(r)
    c = raw_input('next command: ')

我得到的错误是:

$ python testgnu.py
first command: play b c4
gnugo says: ('= \n\n', None)
next command: genmove w
Traceback (most recent call last):
  File "testgnu.py", line 8, in <module>
    r = proc.communicate(c)
  File "/usr/local/Cellar/python/2.7.3/lib/python2.7/subprocess.py", line 754, in communicate
    return self._communicate(input)
  File "/usr/local/Cellar/python/2.7.3/lib/python2.7/subprocess.py", line 1307, in _communicate
    self.stdin.flush()
ValueError: I/O operation on closed file

我正在运行 python 2.7.3(可能没关系,但 gnugo 版本是 3.8)。

其他问题中的一些答案建议pexpect,但我想使用尽可能少的外部库。

【问题讨论】:

    标签: python popen


    【解决方案1】:

    您的问题是Popen.communicate 在执行读写操作后关闭了文件。

    您必须手动调用 proc.stdin.write(...) 来发送进程文本,并手动调用 proc.stdout.read*() 来读取文本:

    while True:
        proc.stdin.write(c)
        r = proc.stdout.readline()
    

    【讨论】:

    • 是的,我想就是这样。现在 stdout.read() 挂起,尽管这似乎是另一个问题。谢谢!
    • stdout.read() 将挂起,因为 .read() 尝试读取 all 输出。相反,请使用.readline()(如我的示例),它一次只能读取一行,或者.read(n),它将读取(最多)n 个字节。
    • 看来问题是它永远不会收到 EOF,所以它永远不会终止。 gnugo 在玩家下棋时几乎立即返回。我尝试将\n 明确写入标准输入,看起来让readline() 至少通过一次(如果我不将\n 写入标准输入,它会挂起),但read() 仍然挂起。
    • 你为什么直接打电话给.read()?您应该只需要致电.readline()... 不?
    • readline() 也挂起。我可以传递 stdin 一堆换行符,然后 readline() 将它们向上传递。目前,我不太明白为什么将换行符添加到 stdin 缓冲区的 END 会使 readline() 多次工作(每次我从 stdout 获得更多我想要的数据时 - 不仅仅是你可能期望的空换行符)。我不介意readline(),只要它最终不会挂起。
    猜你喜欢
    • 1970-01-01
    • 2016-09-17
    • 2015-09-08
    • 2020-03-18
    • 2010-12-06
    • 2021-03-13
    • 2015-03-12
    • 2019-10-27
    相关资源
    最近更新 更多