[three]Bean

Python wrapped in python

Aug 03, 2009 | categories: python View Comments

EDIT 04-26-2011: Check out http://learnpython.org!

So I started a little python project called trypy the other day. Its a TurboGears 2 app in development inspired by the tryruby app written by Why the Lucky Stiff. At the core, I need to be able to interpret python commands in an already running python program. Having learned of the pexpect module, here's what I came up with.

import pexpect

class PythonInterpreter(object):
    def __init__(self, forbidden=[], quiet=True):
        self.forbidden = forbidden
        self.eof = False
        self.lastline = None
        self.py = pexpect.spawn('python')
        self.eoc = "# __end_of_command__"
        if quiet:
            # Chew the first three 'version' lines
            [self.readline() for i in range(3)]
        self.cmd_history = [
                'print "Happy python interpreter reporting for duty."']

    def readline(self):
        self.lastline = self.py.readline().rstrip()
        return self.lastline

    def prompt(self):
        if self.eoc in self.lastline:
            i = self.lastline.index(self.eoc)
            return self.lastline[:i]
        return ">>>"

    def command(self, index):
        return self.cmd_history[index]

    def process(self, cmd):
        lines = []
        self.cmd_history.append(cmd)
        if self.eof:
            lines.append('** PythonInterpreter:  EOF')
        try:
            if any([item in cmd for item in self.forbidden]):
                return ['    "%s"' % cmd, '  Disallowed.  Sorry.']
            self.py.sendline(cmd + "\n" + self.eoc)
            garbage, line = self.readline(), self.readline()
            while self.eoc not in line:
                lines.append(line)
                line = self.readline()
        except Exception, e:
            lines.append( '** PythonInterpreter:  There was an error.' )
            self.eof = True
        return lines
It could be run with a little piece like:
if __name__ == '__main__':
    interp = PythonInterpreter(forbidden=['import'])
    while not interp.eof:
        cmd = raw_input(interp.prompt())
        lines = interp.process(cmd)
        for line in lines:
            print line
    print " Goodbye."

Hope you enjoy. More on trypy soon.

View Comments
blog comments powered by Disqus