[IPython-user] Embedding IPython with py2exe

Michael Foord mike at pcblokes.com
Fri Dec 31 08:36:26 CST 2004


Hello All,

I'm by no means an experienced IPython user. I'm currently working on a
project called 'Movable Python'. This uses py2exe to build a standalone,
portable distribution of Python. Basically a version of python that
doesn't need to be installed. (windoze only I'm afraid because it uses
py2exe).

I've added an interactive interpreter to it (effectively replicating the
'-' and '-i' command line options of python) and have provided the
option of using IPython as the console if the distribution was built
with IPython available.

I cam across the following issue when embedding IPython in a py2exe
program. I thought it might be useful to share the information here in
case any other users attempted to do a similar thing.

The function that calls interactive mode is :

def interactive(localvars):
    """A very simple function to embed an interactive interpreter into
movpy."""
    IPShellEmbed = None
    try:
        from IPython.Shell import IPShellEmbed
    except ImportError:
        pass

    if not IPShellEmbed or IPOFF:
        from code import InteractiveConsole
        con = InteractiveConsole(localvars)
        con.interact()
    else:
        ipshell = IPShellEmbed()
        ipshell()
    sys.exit()

which is called with :
interactive(locals())

Nice and easy !! Except when called from a py2exe program, site.py isn't
imported. This means that 'copyright' and 'credits' aren't available as
builtins. This causes part of IPython to fail. To rectify this I used
the following code straight from site.py :

###########################################
# Functions from site.py
# Used by IPython
# These add objects would normally be available as builtins in the
python environment
# but aren't in a normal py2exe program !

def setquit():
    """Define new built-ins 'quit' and 'exit'.
    These are simply strings that display a hint on how to exit.

    """
    if os.sep == ':':
        exit = 'Use Cmd-Q to quit.'
    elif os.sep == '\\':
        exit = 'Use Ctrl-Z plus Return to exit.'
    else:
        exit = 'Use Ctrl-D (i.e. EOF) to exit.'
    __builtin__.quit = __builtin__.exit = exit


class _Printer(object):
    """interactive prompt objects for printing the license text, a list of
    contributors and the copyright notice."""

    MAXLINES = 23

    def __init__(self, name, data, files=(), dirs=()):
        self.__name = name
        self.__data = data
        self.__files = files
        self.__dirs = dirs
        self.__lines = None

    def __setup(self):
        if self.__lines:
            return
        data = None
        for dir in self.__dirs:
            for filename in self.__files:
                filename = os.path.join(dir, filename)
                try:
                    fp = file(filename, "rU")
                    data = fp.read()
                    fp.close()
                    break
                except IOError:
                    pass
            if data:
                break
        if not data:
            data = self.__data
        self.__lines = data.split('\n')
        self.__linecnt = len(self.__lines)

    def __repr__(self):
        self.__setup()
        if len(self.__lines) <= self.MAXLINES:
            return "\n".join(self.__lines)
        else:
            return "Type %s() to see the full %s text" % ((self.__name,)*2)

    def __call__(self):
        self.__setup()
        prompt = 'Hit Return for more, or q (and Return) to quit: '
        lineno = 0
        while 1:
            try:
                for i in range(lineno, lineno + self.MAXLINES):
                    print self.__lines[i]
            except IndexError:
                break
            else:
                lineno += self.MAXLINES
                key = None
                while key is None:
                    key = raw_input(prompt)
                    if key not in ('', 'q'):
                        key = None
                if key == 'q':
                    break

def setcopyright():
    """Set 'copyright' and 'credits' in __builtin__"""
    __builtin__.copyright = _Printer("copyright", sys.copyright)

    __builtin__.credits = _Printer("credits", """\
Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands
for supporting Python development.  See www.python.org for more
information.""")
    here = os.path.dirname(os.__file__)
    __builtin__.license = _Printer(
    "license", "See http://www.python.org/%.3s/license.html" % sys.version,
    ["LICENSE.txt", "LICENSE"],
        [os.path.join(here, os.pardir), here, os.curdir])


class _Helper(object):
    """Define the built-in 'help'.
    This is a wrapper around pydoc.help (with a twist).

    """

    def __repr__(self):
        return "Type help() for interactive help, " \
               "or help(object) for help about object."
    def __call__(self, *args, **kwds):
        import pydoc
        return pydoc.help(*args, **kwds)

def sethelper():
    __builtin__.help = _Helper()

setquit()
setcopyright()
sethelper()

#########################################

This solves the problem neatly. I've also posted this message to the
py2exe mailing list as well. It could also be fixed by testing for
NameError when they are used in IPython... but that may not be a priority.

By the way 'Movable Python' is nearly ready for it's first release. I'm
just finishing enough docs to make it usable. The project home is at
sourceforge. http://sourceforge.net/projects/movpy

You can grab a copy of what is done so far (incomplete docs) from :
http://www.voidspace.org.uk/cgi-bin/voidspace/downman.py?file=testenv.zip

Regards,


Fuzzy
http://www.voidspace.org.uk/python/index.shtml




More information about the IPython-user mailing list