shell ^[[a - Keyboard shortcuts broken running interactive Python Console from a script




idle previous (3)

You can start an interactive console from inside a script with following code:

import code

# do something here

vars = globals()
vars.update(locals())
shell = code.InteractiveConsole(vars)
shell.interact()

When I run the script like so:

$ python my_script.py

an interactive console opens:

Python 2.7.2+ (default, Jul 20 2012, 22:12:53) 
[GCC 4.6.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>

The console has all globals and locals loaded which is great since I can test stuff easily.

The problem here is that arrows don't work as they normally do when starting an Python console. They simply display escaped characters to the console:

>>> ^[[A^[[B^[[C^[[D

This means that I can't recall previous commands using the up/down arrow keys and I can't edit the lines with the left/right arrow keys either.

Does anyone know why is that and/or how to avoid that?


Answers

Check out readline and rlcompleter:

import code
import readline
import rlcompleter

# do something here

vars = globals()
vars.update(locals())
readline.set_completer(rlcompleter.Completer(vars).complete)
readline.parse_and_bind("tab: complete")
shell = code.InteractiveConsole(vars)
shell.interact()

This is the one I use:

def debug_breakpoint():
    """
    Python debug breakpoint.
    """
    from code import InteractiveConsole
    from inspect import currentframe
    try:
        import readline # noqa
    except ImportError:
        pass

    caller = currentframe().f_back

    env = {}
    env.update(caller.f_globals)
    env.update(caller.f_locals)

    shell = InteractiveConsole(env)
    shell.interact(
        '* Break: {} ::: Line {}\n'
        '* Continue with Ctrl+D...'.format(
            caller.f_code.co_filename, caller.f_lineno
        )
    )

For example, consider the following script:

a = 10
b = 20
c = 'Hello'

debug_breakpoint()

a = 20
b = c
c = a

mylist = [a, b, c]

debug_breakpoint()


def bar():
    a = '1_one'
    b = '2+2'
    debug_breakpoint()

bar()

When executed, this file shows to following behavior:

$ python test_debug.py
* Break: test_debug.py ::: Line 24
* Continue with Ctrl+D...
>>> a
10
>>>
* Break: test_debug.py ::: Line 32
* Continue with Ctrl+D...
>>> b
'Hello'
>>> mylist
[20, 'Hello', 20]
>>> mylist.append(a)
>>>
* Break: test_debug.py ::: Line 38
* Continue with Ctrl+D...
>>> a
'1_one'
>>> mylist
[20, 'Hello', 20, 20]

Considering the portability issues between python2 and python3, you should always specify either version unless your program is compatible with both.

Some distributions are shipping python symlinked to python3 for a while now - do not rely on python being python2.

This is emphasized by PEP 394:

In order to tolerate differences across platforms, all new code that needs to invoke the Python interpreter should not specify python, but rather should specify either python2 or python3 (or the more specific python2.x and python3.x versions; see the Migration Notes). This distinction should be made in shebangs, when invoking from a shell script, when invoking via the system() call, or when invoking in any other context.





python shell