I hacked up this useful wrapper around the python command line shell to allow editing of the last typed in lines of code in an external editor.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
# Python Console with an editable buffer. import os from tempfile import mkstemp from code import InteractiveConsole EDITOR = os.environ.get('EDITOR', 'vim') EDIT_CMD = '\e' class EditableBufferInteractiveConsole(InteractiveConsole): def __init__(self, *args): self.last_buffer =  # This holds the last executed statement InteractiveConsole.__init__(self, *args) def runsource(self, source, *args): self.last_buffer = [ source ] return InteractiveConsole.runsource(self, source, *args) def raw_input(self, *args): line = InteractiveConsole.raw_input(self, *args) if line == EDIT_CMD: fd, tmpfl = mkstemp() os.write(fd, '\n'.join(self.last_buffer)) os.close(fd) os.system('%s %s' % (EDITOR, tmpfl)) line = open(tmpfl).read() os.unlink(tmpfl) tmpfl = '' return line c = EditableBufferInteractiveConsole() c.write(""" Starting the editable interactive console. Edit command is '%s'. """ % EDIT_CMD) c.interact(banner='')
When working in the python command shell, I often end up writing more than 10+ lines of indented code before making a stupid typo. This got irritating enough for me to do something about it. So, here's an 'Interactive Console with an editable buffer'. Hope that people find it useful. To load it up automatically put it in your python startup file [ http://docs.python.org/tut/node4.html#SECTION004240000000000000000 ].
Notes: a) This code works with python 2.3 only due to it's use of tempfile.msktemp(). Maybe somebody could modify it to work with other python versions. b) The editor is selected using the EDITOR environment variable and defaults to 'vim' if it has not been defined. c) The command to invoke the editor is '\e' by default. It may be customized by changing the 'EDIT_CMD' variable.
Use ipython. Get ipython at http://ipython.scipy.org .
Editing multiple lines. Works fine, even with gvim.exe. However, for editing multiple lines like:
a small extension is required before 'return line'. Only the last line entered via the editor is returned by raw_input(). The other lines are handed over to InteractiveConsole.push(), e.g.
Python file extension. Awesome tip! This brings the standard Python shell to 90% of IPython's functionality (for me).
If you change the following line, the temporary file will have a .py file extension which might be helpful::
Make namespace available to the sub-shell. If you add kwargs to __init__ you can easily pass the local namespace to the InteractiveConsole.
For some reason, I've never liked ipython. Just never felt comfortable to me. So this script is a nice find.
Stephen says above that it only works in Python 2.3 -- I guess he meant 2.3+ because it seems fine in 2.5.
The one thing I haven't liked about it so far is that, on my Linux box, the interactive mode it creates don't have regular readline functionality.
However, that is easily fixed! Just add
to the imports at the top of the recipe. Works for me anyway.
Update: Over the years I've improved on this quite a bit. Here's a 'pimped up' version of this: