Python: Custom Interactive Console


Posted:   |  More posts about python

While working on new features that consist of web frontend and a backend API, I found a constant need to manipulate the backend API through python interactive console. Ideally I should implement a command line interface that I can use while waiting for the web frontend to finish but since the API (a class) already has structured methods to access all the API functionalities, a cli interface will just duplicating most of the class API methods.

What tedios when accessing the API through python interactive console is having to re-import all the objects that you need every time you start the interactive console. So an idea pop up - why not create my own custom interactive console with all the objects that I need pre-imported. In python, creating your own interactive console is trivial. The code module has all that you need.

import code

# SomeClass will be available in the interactive console
from yourmodule import SomeClass

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

While simple and just few lines of code, above is not really useful. It doesn't have auto complete and no history, you can't use up/down arrow key to repeat the previous command. A better version:-

import code
import readline
import rlcompleter

# SomeClass will be available in the interactive console
from yourmodule import SomeClass

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

Above is much nicer. Now you have auto complete (type Some<Tab> and you got SomeClass). Cool. But I immediately noticed that the history was not preserved, mean that when I closed the console and start again, it's in blank slate. I can't repeat command in previous session. This actually how the default python console work but I'd already have ~/.pythonrc.py that I defined as PYTHONSTARTUP to setup the tab completion and command history. It seem that my pythonrc.py not being processed by this custom console.

Noticing that the python console from django manage.py shell working correctly with my pythonrc.py, I'd take a look at the implementation code. Look like django has to process PYTHONSTARTUP manually. I'm not really keen on copy-pasting the code from django but there's no way to pass your current enviroment into the console that django created.

In the end, I have to copy the django code into my console function:-

import code
import readline
import rlcompleter

# SomeClass will be available in the interactive console
from yourmodule import SomeClass

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

# copied from django.core.management.commands.shell
for pythonrc in (os.environ.get("PYTHONSTARTUP"),
                 os.path.expanduser('~/.pythonrc.py')):
    if pythonrc and os.path.isfile(pythonrc):
        try:
            with open(pythonrc) as handle:
                exec(compile(handle.read(), pythonrc, 'exec'))
        except NameError:
            pass

code.interact(local=vars)

I found that working directly in the console like this motivate me to write better docstring for each functions and methods as I'd constantly using the help() function to figure out what each function/class/methods are doing. This seem to be much better than having to write dedicated cli interface for your API.

Comments powered by Disqus

About me

Web developer in Malaysia. Currently work at MARIMORE Inc building internet services using Python and Django web framework.

ImportError is an error message emitted by Python when it failed to load certain module as requested by programmer. It's a very common error when someone new to the language trying it out. This website on the same theme, will try provide help for newcomers on any technologies to overcome their first hurdle.

Others

I can also be found at the following sites:-

  • http://k4ml.blogspot.com/
  • http://k4ml.github.io/
  • http://metak4ml.blogspot.com/
  • http://www.mydev.my/
  • http://github.com/k4ml/

Disclaimers

The postings on this site are my own and don't necessarily represent my employer's positions, strategies or opinions.

Share