[Tutor] re: running an interactive program from a script

Michael Dunn Michael.Dunn at mpi.nl
Mon Jan 12 04:04:37 EST 2004


Thanks Lee for the pointer to the pexpect module, it was exactly what I
needed. There are notes in the faq on the pexpect webpage about why a
simple pipe wouldn't work for the sort of thing I need.

Anyway, I've written a test program and it works. I'd appreciate anybody's
comments (specific or general -- Python is my first computer language,
barring a bit of fiddling with BASIC on a Vic20 at the dawn of time).

This is the parent program using pexpect (the child program is copied
below). Run the parent and it will run the child itself (should be named
sample.py):

###
#!/usr/bin/env python
# parent.py

import re
import pexpect

def main():
    child = pexpect.spawn('python sample.py')
    while 1:
        index = child.expect(['> ', pexpect.EOF])
        if index == 0:
            print child.before.strip()
            s = select_switch(child.before)
            child.sendline(s)
        else:
            print child.before
            #print child.after
            break

def select_switch(s):
    r = re.search(r'\(F\)loats: ([a-zA-Z]+).*\(D\)uck: ([a-zA-Z]+)', s, re.DOTALL)
    values = r.groups()
    current = {'float':values[0], 'duck':values[1]}
    if current['float'] != target['float']:
        return 'f'
    elif current['duck'] != target['duck']:
        return 'd'
    else:
        return 'q'


target = {'float':'Maybe', 'duck':'Maybe'}
# these values could come from command line switches or a configuration file

main()
###

This is the sample of the kind of interactive program I want to automate
(copied from my initial query):

###
#!/usr/bin/env python
# sample.py
# the parent assumes this script is called 'sample.py' and is in the
# same directory

prompt = """Settings:
 (F)loats: %(float)s
 Is (D)uck: %(duck)s
Enter F or D to change a setting, Q to quit
> """
settings = {'float':'Yes', 'duck':'No'}
toggle = {'Yes':'Maybe','Maybe':'No','No':'Yes'}
selection = ''

while selection.upper() != 'Q':
    selection = raw_input((prompt % settings))
    if selection.upper() == 'F':
        settings['float'] = toggle[settings['float']]
    if selection.upper() == 'D':
        settings['duck'] = toggle[settings['duck']]

print 'Settings are:', settings
###

I'm currently working on doing a similar thing with one of the programs in
the PHYLIP package. There are a few additional problems -- changing one
option in PHYLIP will occasionally cause other options to be added or
removed, and selecting some options calls forth additional questions. The
worst problem is that there's no standard prompt character used, so it's
hard to decide what to get child.expect(???) to look for.

--Michael



More information about the Tutor mailing list