Skip to content

Instantly share code, notes, and snippets.

@rduplain
Last active July 21, 2025 21:06
Show Gist options
  • Save rduplain/899f6a5e583a85668822 to your computer and use it in GitHub Desktop.
Save rduplain/899f6a5e583a85668822 to your computer and use it in GitHub Desktop.

Revisions

  1. rduplain revised this gist Jul 15, 2014. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -94,6 +94,7 @@ Selected real-world use cases of `code.InteractiveConsole`:

    1. interactive step interpreter for [Cucumber-style][7] steps, with [behave][8]
    2. send bytes interactively to test a network protocol driver
    3. command REPL for an instrument controller


    [1]: https://docs.python.org/3.4/library/code.html
  2. rduplain revised this gist Jul 15, 2014. 1 changed file with 5 additions and 5 deletions.
    10 changes: 5 additions & 5 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -1,10 +1,10 @@
    ## `import code`
    ### `import code`

    This is a demonstration of the Python [code][1] module, which allows for an
    interactive interpreter to be embedded into a Python program.


    ### `code.interact(banner=None, readfunc=None, local=None)`
    ##### `code.interact(banner=None, readfunc=None, local=None)`

    Convenience function to run a read-eval-print loop. This creates a new instance
    of [`InteractiveConsole`][2] and sets readfunc to be used as the
    @@ -15,7 +15,7 @@ instance is then run with banner passed as the banner to use, if provided. The
    console object is discarded after use.


    ### python interact.py
    ##### python interact.py

    `code.interact` is useful for:

    @@ -37,14 +37,14 @@ Example:
    $


    ### `class code.InteractiveConsole(locals=None, filename="<console>")`
    ##### `class code.InteractiveConsole(locals=None, filename="<console>")`

    Closely emulate the behavior of the interactive Python interpreter. This class
    builds on [`InteractiveInterpreter`][6] and adds prompting using the familiar
    `sys.ps1` and `sys.ps2`, and input buffering.


    ### python console.py
    ##### python console.py

    `code.InteractiveConsole` is useful when you want to customize the REPL:

  3. rduplain created this gist Jul 15, 2014.
    106 changes: 106 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,106 @@
    ## `import code`

    This is a demonstration of the Python [code][1] module, which allows for an
    interactive interpreter to be embedded into a Python program.


    ### `code.interact(banner=None, readfunc=None, local=None)`

    Convenience function to run a read-eval-print loop. This creates a new instance
    of [`InteractiveConsole`][2] and sets readfunc to be used as the
    [`InteractiveConsole.raw_input()`][3] method, if provided. If local is
    provided, it is passed to the [`InteractiveConsole`][2] constructor for use as
    the default namespace for the interpreter loop. The interact() method of the
    instance is then run with banner passed as the banner to use, if provided. The
    console object is discarded after use.


    ### python interact.py

    `code.interact` is useful for:

    1. Pre-loading `python` interactive interpreter. ([flask-script][4] does this.)
    2. Embedding an interactive interpreter in a program, with an *internal* DSL.
    3. Quick interactive debugging (you probably want [`pdb.set_trace()`][5]).

    Example:

    $ python interact.py

    >>> foo
    'this is foo'
    >>> bar
    'this is bar'
    >>> 6 * 7
    42
    >>>
    $


    ### `class code.InteractiveConsole(locals=None, filename="<console>")`

    Closely emulate the behavior of the interactive Python interpreter. This class
    builds on [`InteractiveInterpreter`][6] and adds prompting using the familiar
    `sys.ps1` and `sys.ps2`, and input buffering.


    ### python console.py

    `code.InteractiveConsole` is useful when you want to customize the REPL:

    1. Changing the REPL behavior of the `python` interactive interpreter.
    2. Embedding an interactive interpreter in a program, with an *external* DSL.
    3. Provide a scripting interface for an external DSL.

    Example:

    $ python console.py
    > room
    No one is in the room.
    > enter John Mary Joseph
    John enters the room.
    Mary enters the room.
    Joseph enters the room.
    > exit Joseph
    Joseph leaves the room.
    > room
    In the room: John, Mary
    >
    $

    Non-interactive usage:

    $ echo 'room' | python console.py
    No one is in the room.
    $

    Non-interactive scripting (could update code to take files on sys.argv):

    python console.py <<EOF
    enter John Mary Joseph
    exit Joseph
    room
    EOF

    ... produces output:

    John enters the room.
    Mary enters the room.
    Joseph enters the room.
    Joseph leaves the room.
    In the room: John, Mary

    Selected real-world use cases of `code.InteractiveConsole`:

    1. interactive step interpreter for [Cucumber-style][7] steps, with [behave][8]
    2. send bytes interactively to test a network protocol driver


    [1]: https://docs.python.org/3.4/library/code.html
    [2]: https://docs.python.org/3.4/library/code.html#code.InteractiveConsole
    [3]: https://docs.python.org/3.4/library/code.html#code.InteractiveConsole.raw_input
    [4]: http://flask-script.readthedocs.org/
    [5]: https://docs.python.org/3.4/library/pdb.html
    [6]: https://docs.python.org/3.4/library/code.html#code.InteractiveInterpreter
    [7]: http://cukes.info/
    [8]: http://pythonhosted.org/behave/
    117 changes: 117 additions & 0 deletions console.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,117 @@
    import code
    import shlex
    import sys

    from sys import stderr


    class CommandRunner(object):
    "Simple demo."
    def __init__(self):
    self.commands = {}

    def command(self, name, fn):
    self.commands[name] = fn

    def run(self, line):
    tokens = shlex.split(line, comments=True)
    command, args = tokens[0], tokens[1:]
    if command not in self.commands:
    print('{}: no such command'.format(command), file=stderr)
    return
    result = self.commands[command](*args)
    if result is not None:
    print(result)


    class Console(object):
    ps1 = '> '
    ps2 = '. '

    def __init__(self, runner):
    self.runner = runner

    def run(self, fd):
    for line in fd:
    self.runner.run(line)

    def interact(self, locals=None):
    class LambdaConsole(code.InteractiveConsole):
    def runsource(code_console, source, filename=None, symbol=None):
    # Return True if more input needed, else False.
    try:
    self.runner.run(source)
    except SystemExit:
    raise
    except:
    code_console.showtraceback()
    return False

    # import readline to support line editing within console session.
    try:
    import readline; readline
    except ImportError:
    pass

    # Patch ps1 & ps2 for interaction. Note sys.psX may be unset.
    ps1, ps2 = getattr(sys, 'ps1', None), getattr(sys, 'ps2', None)
    try:
    sys.ps1, sys.ps2 = self.ps1, self.ps2
    LambdaConsole(locals=locals, filename="<demo>").interact(banner='')
    finally:
    sys.ps1, sys.ps2 = ps1, ps2

    def run_in_main(self, fd=None, interact=False):
    if fd is None:
    fd = sys.stdin
    if fd.isatty():
    self.interact()
    else:
    try:
    self.run(fd=fd)
    except Exception as err:
    print(err, file=stderr)
    return 1
    return 0


    class Room(object):
    "Simple demo."

    def __init__(self):
    self.people = set()

    def enter(self, *people):
    for person in people:
    if person in self.people:
    print('{} is already in the room.'.format(person), file=stderr)
    else:
    print('{} enters the room.'.format(person))
    self.people.add(person)

    def exit(self, *people):
    for person in people:
    if person in self.people:
    print('{} leaves the room.'.format(person))
    self.people.remove(person)
    else:
    print('{} is not in the room.'.format(person), file=stderr)

    def room(self):
    if self.people:
    print('In the room: {}'.format(', '.join(self.people)))
    else:
    print('No one is in the room.')


    def main(fd=None):
    room = Room()
    runner = CommandRunner()
    runner.command('enter', room.enter)
    runner.command('exit', room.exit)
    runner.command('room', room.room)
    return Console(runner).run_in_main(fd)


    if __name__ == '__main__':
    sys.exit(main())
    11 changes: 11 additions & 0 deletions interact.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,11 @@
    import code


    def interact():
    foo = 'this is foo'
    bar = 'this is bar'
    code.interact(banner='', local=locals())


    if __name__ == '__main__':
    interact()