almostflan
almostflan

Reputation: 640

Wrapping an interactive CLI in python

I am trying to wrap gnugo in a python script.

I've gone over the other questions in SO about wrapping CLI applications here and here and though they've helped somewhat, I haven't been able to get my script to work completely. It appears the process is killed after the first input from stdin.

The script looks like this:

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

The error I'm getting is this:

$ 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

I am running python 2.7.3 (and it probably doesn't matter but the gnugo version is 3.8).

Some answers in the other questions suggested pexpect but I'd like to use as few external libraries as possible.

Upvotes: 6

Views: 7666

Answers (1)

David Wolever
David Wolever

Reputation: 154484

Your issue is that Popen.communicate closes the file after performing its reads and writes.

You will have to manually call proc.stdin.write(...) to send the process text and proc.stdout.read*() to read text:

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

Upvotes: 8

Related Questions