Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wrapping an interactive CLI in python

Tags:

python

popen

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.

like image 968
almostflan Avatar asked Jun 09 '12 15:06

almostflan


1 Answers

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()
like image 54
David Wolever Avatar answered Oct 02 '22 05:10

David Wolever