dlo.me

Supercharge Your Python Shell

I've been using and working with Python in a professional context for around 8 years. So it came sort of a shock that something so useful, so obvious, was unfamiliar to me until around a week and a half ago.

It involves a little file called .pythonrc that lives in your home directory. To get it to work, you'll need to define an environment variable called PYTHONSTARTUP, like so:

export PYTHONSTARTUP="$HOME/.pythonrc"

(Major hat tip to kasnalin on Reddit for pointing out that I'd forgotten to include this important piece of info in an earlier version of the post.)

If you're a Python developer, no doubt you open up a Python shell countless times per day. Whether you use the regular Python shell, or another one such as IPython, it's all the same. Open up the shell, import a few useful modules, and start playing around.

Maybe you find yourself importing the same modules over and over again. Maybe you leave a single shell open all the time since it's such a pain to re-type those commands.

I spend a lot of time working with Django, so I'd gotten pretty used to typing ./manage.py shell and then from app import models to start playing around with objects in my database.

Well, I got to wondering what this .pythonrc could do to help me out with this, so I dumped in the following code:

try:
    from app import models
    from django.conf import settings
except:
    print("\nCould not import Django modules.")
else:
    print("\nImported Django modules.")

Not expecting this to work at all, I ran my trusty Django shell, and voilĂ :

$ ./manage.py shell

Imported Django modules.
Python 2.7.6 (default, Jan  6 2014, 13:22:56)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.2.79)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>

It's like magic. No more reverse searching my shell history to import commonly-used modules. If I find myself using one often enough, I just add it into my .pythonrc and it's there for me every time.

I play around Redis a bunch, so here's another chunk of code I plopped in there.

from redis import StrictRedis as Redis

r = Redis()

Now, I can just open up the shell and use r to play with Redis.

Here's another one I'm pretty fond of. I'm a big fan of tab-completion and readline support. So I put this in my .pythonrc too:

try:
    import readline
except ImportError:
    print("Module readline not available.")
else:
    import rlcompleter
    if 'libedit' in readline.__doc__:
        readline.parse_and_bind("bind ^I rl_complete")
    else:
        readline.parse_and_bind("tab: complete")

Works like a charm.

Below is my full .pythonrc, in all of its glory (also available as a Gist).

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
# vim: set ft=python :

from __future__ import print_function

import json
import sys
import datetime

from redis import StrictRedis as Redis

r = Redis()

try:
    import readline
except ImportError:
    print("Module readline not available.")
else:
    import rlcompleter
    if 'libedit' in readline.__doc__:
        readline.parse_and_bind("bind ^I rl_complete")
    else:
        readline.parse_and_bind("tab: complete")

try:
    from app import models
    from django.conf import settings
except:
    print("\nCould not import Django modules.")
else:
    print("\nImported Django modules.")

try:
    from dateutil.parser import parse as parse_date
except ImportError:
    print("\nCould not import dateutil.")