views:

493

answers:

2

Hello,

I'd like to be able to "up-arrow" to commands that I input in a previous Python interpreter. I have found the readline module which offers functions like: read_history_file, write_history_file, and set_startup_hook. I'm not quite savvy enough to put this into practice though, so could someone please help? My thoughts on the solution are:

(1) Modify .login PYTHONSTARTUP to run a python script. (2) In that python script file do something like:

def command_history_hook():
    import readline
    readline.read_history_file('.python_history')
command_history_hook()

(3) Whenever the interpreter exits, write the history to the file. I guess the best way to do this is to define a function in your startup script and exit using that function:

def ex():
    import readline
    readline.write_history_file('.python_history')
    exit()

It's very annoying to have to exit using parentheses, though: ex(). Is there some python sugar that would allow ex (without the parens) to run the ex function?

Is there a better way to cause the history file to write each time? Thanks in advance for all solutions/suggestions.

Also, there are two architectural choices as I can see. One choice is to have a unified command history. The benefit is simplicity (the alternative that follows litters your home directory with a lot of files.) The disadvantage is that interpreters you run in separate terminals will be populated with each other's command histories, and they will overwrite one another's histories. (this is okay for me since I'm usually interested in closing an interpreter and reopening one immediately to reload modules, and in that case that interpreter's commands will have been written to the file.) One possible solution to maintain separate history files per terminal is to write an environment variable for each new terminal you create:

def random_key()
    ''.join([choice(string.uppercase + string.digits) for i in range(16)])

def command_history_hook():
    import readline
    key = get_env_variable('command_history_key')
    if key:
        readline.read_history_file('.python_history_{0}'.format(key))
    else:
        set_env_variable('command_history_key', random_key())

def ex():
    import readline
    key = get_env_variable('command_history_key')
    if not key:
        set_env_variable('command_history_key', random_key())
    readline.write_history_file('.python_history_{0}'.format(key))
    exit()

By decreasing the random key length from 16 to say 1 you could decrease the number of files littering your directories to 36 at the expense of possible (2.8% chance) of overlap.

+2  A: 

Try using IPython as a python shell. It already has everything you ask for. They have packages for most popular distros, so install should be very easy.

maksymko
Agree. I have been using ipython for a while and it is fantastic, it has auto-completition and the history feature you are looking for.
dalloliogm
I'm using IPython (on Windows today), but when I run it, my up/down arrow keys do not give me any command history. What am I doing wrong?
Tartley
SOLUTION: 'easy_install pyreadline' to have up/down arrow keys browse command history on Windows. Plus some other things (like colors!) work now.
Tartley
+4  A: 

I think the suggestions in the Python documentation pretty much cover what you want. Look at the example pystartup file toward the end of section 13.3:

or see this page:

But, for an out of the box interactive shell that provides all this and more, take a look at using IPython:

ars
+1 for iPython.
Daniel Roseman
Thanks, the env variable PYTHONSTARTUP and function atexit.register are what I wanted.Based on your input, though, I'll probably just be using iPython. thanks!
DGGenuine