ActiveState Code

Recipe 473900: History and completion for the python shell


This script creates a history file to share between your interactive python sessions, controlling its size in either lines or bytes. You have to put it in your PYTHONSTARTUP environment variable. As it uses readline, it only works under Unix systems. It also binds the tab key to complete words in the shell

Python
 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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#!/usr/bin/env python

#Configuration section

hist_file = '/home/your_user/.py_history'
max_size_bytes = 1000000
max_size_lines = 10000

#Code section, no need to modify this

import readline
import rlcompleter
import atexit
import sys
from os.path import getsize

def reset_file(size,max_size,reason):
        try:
                print "Resetting history file %s because it exceeded %s %s; it has %s.\n" % (hist_file,max_size,reason,size,)
                f = open(hist_file,'w')
                f.close()
        except IOError, e:
                print "Couldn't reset history file %s [%s].\n" % (hist_file,e,)

def safe_getsize(hist_file):
        try:
                size = getsize(hist_file)
        except OSError:
                size = 0
        return size

lines = 0
size = safe_getsize(hist_file)

if size > max_size_bytes:
        reset_file(size,max_size_bytes,"bytes")
else:
        try:
                readline.read_history_file(hist_file)
                lines = readline.get_current_history_length()
                if lines > max_size_lines:
                        try:
                                readline.clear_history()
                        except NameError, e:
                                print "readline.clear_history() not supported (%s), please delete history file %s by hand.\n" % (e,hist_file,)
                        reset_file(lines,max_size_lines,"lines")
        except IOError:
                try:
                        f = open(hist_file,'a')
                        f.close()
                except IOError:
                        print "The file %s can't be created, check your hist_file variable.\n" % hist_file

size = safe_getsize(hist_file)

print "Current history file (%s) size: %s bytes, %s lines.\n" % (hist_file,size,readline.get_current_history_length(),)

readline.parse_and_bind("tab: complete")

atexit.register(readline.write_history_file,hist_file)

Discussion

This is helpful when you use your shell to do repetitive tasks, as it preserves the commands you have typed through different shell sessions. This probably isn't the best possible implementation, but I think it's useful, and it avoids the pitfall of creating huge history files that would make python have great startup times.

Comments

  1. 1. At 6:28 a.m. on 20 feb 2006, Andrew Gwozdziewycz said:

    a more compact version...

    import os, readline, sys
    try:
       histfile = os.path.join(os.environ["HOME"], ".python_history")
       if sys.argv[0] == '-':
          try:
             readline.read_history_file(histfile)
          except IOError:
             pass
          import atexit
          atexit.register(readline.write_history_file, histfile)
    except IndexError:
       pass
    del os, histfile, readline, sys
    

    Though, this doesn't have a size limit or anything. The only difference here is it saves history only when starting python with a '-'... (i.e. python -). Oh, and there's no tab complete, but that could easily be added.

    Also, in your version, there's no reason to keep those variables around, so maybe del's would be in order.

  2. 2. At 8:19 a.m. on 20 feb 2006, Filip Salomonsson said:

    Another version. Here's what I use (strikingly similar):

    import os, readline, rlcompleter, atexit
    
    history_file = os.path.join(os.environ['HOME'], '.python_history')
    try:
        readline.read_history_file(history_file)
    except IOError:
        pass
    readline.parse_and_bind("tab: complete")
    readline.set_history_length(1000)
    atexit.register(readline.write_history_file, history_file)
    
    del os, readline, rlcompleter, atexit, history_file, __file__
    

    The history file is created on exit if it didn't already exist, and readline.set_history_length(1000) limits the number of entries saved.

  3. 3. At 9:27 p.m. on 20 feb 2006, Tnoo Luthi said:

    Why not ipython? Ipython (http://ipython.scipy.org) works on all platforms and does all of the above, and so much more. It is somewhat bigger, of course ;-)

Sign in to comment