Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Persistent Python Command-Line History

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.

like image 530
Carl G Avatar asked Jul 27 '09 07:07

Carl G


1 Answers

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:

  • http://docs.python.org/tutorial/interactive.html

or see this page:

  • http://rc98.net/pystartup

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

  • http://ipython.scipy.org/moin/
like image 55
ars Avatar answered Oct 16 '22 02:10

ars