Chapter 2. IPython

One of Python’s strengths is its interactive interpreter, or shell. The shell provides a way to quickly test ideas, test features and interfaces of modules you are working with, and perform some one-off tasks for which you would otherwise have written a three line script. The way that we tend to code is by simultaneously running a text editor and a Python prompt (actually, an IPython prompt, but we’ll get to that in a moment), frequently interacting with them both, switching back and forth between shell and editor, and often pasting code from one to the other. This approach allows us to see immediate results from Python about the way it handles code and to quickly get the code in the text editor working the way we want it to.

At its heart, IPython is a bundle of interactive Python goodness. It is an amazing Python shell, far superior to the standard Python shell. It also provides the ability to create highly customized console-based command environments; it allows for easy inclusion of an interactive Python shell into any Python application; and it can even be used as a system shell, with some level of success. This chapter will focus on using IPython to improve your productivity on *nix-shell and Python-related tasks.

IPython also has an active, incredibly helpful community behind it. You can sign up for the mailing list at http://lists.ipython.scipy.org/mailman/listinfo/ipython-user. There is an excellent wiki at http://ipython.scipy.org/moin. And, as part of the wiki, there is a cookbook at http://ipython.scipy.org/moin/Cookbook. So, you can read or contribute to any of these resources as you wish. Another area that you can contribute to is the development of IPython. IPython development recently switched to a distributed source control system, so you can just branch their code and start hacking. And if you do something that could benefit others, you can submit your changes to them.

Installing IPython

There are a few options for installing IPython. The first and most rudimentary is source distribution. The download page for IPython is located at http://ipython.scipy.org/dist/. At the time of this writing, the latest IPython release was 0.8.2 and 0.8.3 was nearing completion. To install from source, go to http://ipython.scipy.org/dist/ipython-0.8.2.tar.gz and download the tar.gz file. You can unzip the downloaded file using tar zxvf ipython-0.8.2.tar.gz. The unzipped directory will contain a setup.py file. Call Python on the setup.py with an install paramater (e.g., python setup.py install). This will install the libraries for IPython in your site-packages directory and create an ipython script in your scripts directory. On UNIXes, this is typically the same directory that the python binary is located in. If you are using a python that was installed with your system’s package manager, it (and consequently ipython) will likely be located in /usr/bin. We’ve installed the source distribution of the latest development code for IPython, so you will see 0.8.3 in some examples.

A second option for installing IPython is to use a package from your system’s package management system. On Debian and Ubuntu, .deb packages are available to install. Installation is simply apt-get install ipython. Ubuntu installs the IPython libraries to the appropriate location (/usr/share/python-support/ipython with a tangle of .pth files and symbolic links to make things work right). It also installs the ipython binary to /usr/bin/ipython.

The third option for installing IPython is to use a Python package. You may be unaware that such a thing as a Python package exists, but they do. Python packages are files bundled together in a ZIP format, and the resulting file has a .egg extension. Eggs (as they are often simply called) can be installed with the easy_install utility. One of the cool features of easy_install is that it checks a central repository of eggs and then figures out what to install. There is a bit more to it behind the scenes, but as far as the user is concerned, it is relatively easy.The repository is called the Python Package Index or PyPI for short (though some affectionately call it the Python CheeseShop). To easy_install IPython, simply log on as the user that has permissions to write to your Python’s site-packages directory and easy_install ipython.

The fourth option is to use IPython without installing it at all. “What?” You might well ask. Well, if you download the source distribution and just run ipython.py from the root of that set of files, you will have a running instance of the IPython version that you downloaded. That can be a pretty useful way to go if you don’t want to clutter up your site-packages directory, but you’ll want to be aware of some limitations. If you run IPython from the directory to which you untarred it and you don’t modify your PYTHONPATH environment variable, you won’t be able to use it as a library.

Basic Concepts

After you’ve installed IPython, when you run ipython for the first time, you will see something like this:

jmjones@dink:~$ ipython
**********************************************************************
Welcome to IPython. I will try to create a personal configuration directory
where you can customize many aspects of IPython's functionality in:

/home/jmjones/.ipython

Successful installation!

Please read the sections 'Initial Configuration' and 'Quick Tips' in the
IPython manual (there are both HTML and PDF versions supplied with the
distribution) to make sure that your system environment is properly configured
to take advantage of IPython's features.

Important note: the configuration system has changed! The old system is
still in place, but its setting may be partly overridden by the settings in
"~/.ipython/ipy_user_conf.py" config file. Please take a look at the file
if some of the new settings bother you.


Please press <RETURN> to start IPython.

After you hit the Return key, your cursor will be waiting for you at a prompt, and IPython will display the following text:

jmjones@dinkgutsy:stable-dev$ python ipython.py 
Python 2.5.1 (r251:54863, Mar  7 2008, 03:39:23) 
Type "copyright", "credits" or "license" for more information.

IPython 0.8.3.bzr.r96 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object'. ?object also works, ?? prints more.

In [1]:

Interacting with IPython

It’s common to feel some helplessness when presented with a new shell prompt for the very first time. It’s not at all obvious exactly what to do. Remember the first time you logged into a Unix box and were presented with a (ba|k|c|z)sh prompt? Since you are reading this book, we assume you have attained some level of familiarity over the Unix shell. If that is the case, then gaining some level of mastery over IPython will be easy.

One of the reasons that it is unclear what you should do when you first see the IPython prompt, is that what you can do is virtually unlimited. So it is more appropriate to think in terms of what you want to do. All of the features of the Python language are available to you from within the IPython prompt. Plus, there are a number of IPython “magic” functions available to you. And you can easily execute any Unix shell command from within IPython and then store the output into a Python variable. The next few examples will demonstrate what you can expect from IPython with its default configuration.

Here are the input and output of a few simple assignment operations:

In [1]: a = 1

In [2]: b = 2

In [3]: c = 3

This doesn’t look much different from what you would see if you entered the same thing at a standard Python prompt. We simply assigned 1, 2, 3 to a, b, c, respectively. The biggest difference you’ll see between the IPython and standard Python shells is that IPython gives you a numbered prompt.

Now that we have values (1, 2, and 3) stored in a few variables (a, b, and c, respectively), we can see the values that those variables contain:

In [4]: print a
1

In [5]: print b
2

In [6]: print c
3

This is a contrived example. We just typed in the values, so we can, at worst, just scroll up to see what the values were. Each variable that we displayed took six characters more than was necessary to display its value. Here’s a slightly less verbose way of showing the value:

In [7]: a
Out[7]: 1

In [8]: b
Out[8]: 2

In [9]: c
Out[9]: 3

While the outlook values look pretty much the same, there is a difference. The print statements use the “unofficial” string representation, while the bare variable names use the “official” string representation. This distinction is typically more important when you are dealing with custom classes than when you are dealing with built-in classes. Here is an example of the different string representations in use:

In [10]: class DoubleRep(object):
....:     def __str__(self):
....:         return "Hi, I'm a __str__"
....:     def __repr__(self):
....:         return "Hi, I'm a __repr__"
....:
....:

In [11]: dr = DoubleRep()

In [12]: print dr
Hi, I'm a __str__

In [13]: dr
Out[13]: Hi, I'm a __repr__

We created the class DoubleRep with two methods, __str__ and __repr__, to demonstrate the difference between printing an object and showing the “official” string representation of it. The special method __str__ on an object will be called when the “unofficial” string representation is needed. The special method __repr__ on an object will be called when the “official” representation is needed. After instantiating our DoubleRep object and assigning the variable dr as its value, we printed out the value of dr. The __str__ method was called. Next, we simply typed in the variable name and the __repr__ method was called. The point of all this is that when we simply type in the name of a variable, the result that IPython displays is the “official” string representation. When we tell IPython to print the variable, we see the “unofficial” string representation. In Python in general, __str__ is what gets called when you call str(obj) on an object or when it is used in a formatted string like this: "%s" % obj. When repr(obj) gets called, or when it is used in a formatting string like this: "%r" % obj, __repr__ is what gets called.

This behavior isn’t particular to IPython, however. This is exactly how the standard Python shell works. Here is the same DoubleRep example using the standard Python shell:

>>> class DoubleRep(object):
...    def __str__(self):
...        return "Hi, I'm a __str__"
...    def __repr__(self):
...        return "Hi, I'm a __repr__"
... 
>>> 
>>> dr = DoubleRep()
>>> print dr
Hi, I'm a __str__
>>> dr
Hi, I'm a __repr__

You may have noticed that the standard Python prompt and the IPython prompt look different. The standard Python prompt consists of three greater-than signs (>>>), whereas the IPython prompt consists of the word “In,” followed by a number in brackets, followed by a colon (In [1]:). A likely reason for this is that IPython keeps track of the commands that you input and stores them in a list named In. After you’ve assigned 1, 2, 3 to a, b, c, in the previous example, here is what the In list would look like:

In [4]: print In
['
', u'a = 1
', u'b = 2
', u'c = 3
', u'print In
']

The output from the IPython prompt is different from the output from the standard Python prompt as well. The IPython prompt seems to distinguish between two types of output: written output and evaluated output. In reality, IPython really doesn’t distinguish between the two types. What happens is that print calls are a side effect of computation; so IPython doesn’t see them, and so it can’t trap them. These print side effects just wind up on stdout, which is where the calling process sent them. However, as IPython executes user’s code, it checks return values. If the return value is not None, it prints it at an Out [number]: prompt.

The standard Python prompt does not even appear to distinguish between these two types of output. If a statement that you typed into an IPython prompt evaluates to some value other than None, IPython will write it to a line that starts with Out, followed by a bracketed number, followed by a colon, and, finally, followed by the value that the statement evaluated to (i.e., Out[1]: 1). Here is an example of what happens when IPython assigns an integer to a variable, evaluates the variable, displays its value, and then prints out that value. Note the differences among the tasks of assigning to the variable, showing what the variable value evaluates to, and printing the value of the variable. First, the IPython prompt:

In [1]: a = 1

In [2]: a
Out[2]: 1

In [3]: print a
1

In [4]:

Next, the standard Python prompt:

>>> a = 1
>>> a
1
>>> print a
1
>>>

There is really no difference between the way IPython and Python assign the integer, IPython prompt, and the standard Python prompt. Both immediately returned an input prompt to the user. But in showing the “official” string representation of a variable, IPython and standard Python are different. IPython shows only an Out prompt, while Python showed the output. For printing, there was no difference; both showed the output with no prompt.

This In [some number]: and Out [some number]: business may have you wondering if there is a deeper difference between IPython and standard Python, or if the difference is purely cosmetic. The difference is definitely deeper. In fact, the difference represents an area of functionality that places IPython into what seems to be a different category of interactive shell from the standard Python shell.

There are two built-in variables that you will want to be aware of. They are In and Out. The former is an IPython input list object and the latter is a dict object. Here is what type says about the ins and outs of In and Out:

In [1]: type(In)
Out[1]: <class 'IPython.iplib.InputList'>

In [2]: type(Out)
Out[2]: <type 'dict'>

After you start using In and Out, this will make sense.

So, what do these datatypes hold?

In [3]: print In
['
', u'type(In)
', u'type(Out)
', u'print In
']

In [4]: print Out
{1: <class 'IPython.iplib.InputList'>, 2: <type 'dict'>}

As you may expect, In and Out, respectively, hold the input that you typed in and the output that non-None statements and expressions evaluated to. Since each line must necessarily have input, it would seem to make sense to keep track of input in some sort of list-like structure. But keeping track of the output in a list-like structure would result in a number of empty fields or fields containing only None. So, since not every line will have evaluatable non-None output, it makes sense to keep track of output in a dictionary-like data structure or even a pure dict object.

Tab Completion

Another of the incredibly useful data-entry features of IPython is tab completion by default. The standard Python shell has tab-completion capability if it is compiled with readline support, but you have to do something like the following:

>>> import rlcompleter, readline
>>> readline.parse_and_bind('tab: complete')

This will give us functionality as follows:

>>> import os
>>> os.lis<TAB>
>>> os.listdir
>>> os.li<TAB><TAB>
os.linesep  os.link     os.listdir

After importing rlcompleter and readline and setting the readline tab complete option, we were able to import os, type in os.lis, hit the Tab key once, and have it complete to os.listdir. We were also able to enter os.li, hit the Tab key twice, and get a list of possible completions.

We get this same behavior with IPython for without any extra configuration necessary. Well, it’s free with the standard Python shell as well, but with IPython, it’s the default behavior. Here is the previous example run with IPython:

In [1]: import os

In [2]: os.lis<TAB>
In [2]: os.listdir
In [2]: os.li<TAB>
os.linesep  os.link     os.listdir

Notice that we had to hit the Tab key only once on the last part of the example.

The os.TAB example really only shows off the attribute lookup and completion functionality of IPython, but another cool thing that IPython will complete on is module imports. Open a new IPython shell so that you can see IPython help us find a module to import:

In [1]: import o
opcode       operator     optparse     os           os2emxpath   ossaudiodev  

In [1]: import xm
xml        xmllib     xmlrpclib

Notice that all of the items that import completed on were modules, so this wasn’t accidental behavior. This is a feature.

IPython exposes two types of completion: “complete” and “menu-complete.” The difference between the two is that “complete” expands the current “word” as far as it can and then provides a list of alternatives, while “menu-complete” expands the word fully to match one of the alternatives, and then each subsequent press of the Tab key morphs the word into the next alternative. IPython’s default completion option is “complete.” We’ll get into configuring your IPython in just a bit.

Magic Edit

The last basic input and output topic we will cover is the “magic” edit function. (We will go over magic functions in the next section.) Strictly line-oriented user interaction with a shell has tremendous, but limited, usefulness. Since that statement sounds like a contradiction, we’ll unpack it. Typing commands into a shell one line at a time is very useful. You type in a command; the shell goes off and does its thing; you sometimes sit and wait for it to return; you type in your next command. This is not a bad cycle. In fact, it’s quite effective. But sometimes it would be nice to work with a block of lines all at the same time. And it would be nice to work with them in your text editor of choice, although readline support in IPython does improve its usefulness, in this respect. We are aware of using a text editor to create Python modules, but that isn’t what we’re talking about here. We’re talking about more of a compromise between line-oriented input and text editor input to feed commands to the shell. If we can say that adding support for working with blocks of lines of commands would be better, then we can say that a strictly line-oriented interface is limited. So, we can say that a strictly line-oriented interface is exceptionally useful but limited at the same time.

The magic edit function acts as the compromise we just mentioned between pure command-line interaction with the Python shell and interaction using a text editor. The benefit of the compromise is that you have the full power of both environments at your fingertips. You have the benefit of the full-featured power of your text editor of choice. You can easily edit blocks of code and change lines of code around within a loop or a method or function. Plus, you have the nimbleness and agility that comes from directly interacting with the shell. When you combine these two approaches to working with code, a synergistic benefit emerges. You are able to maintain the environment you were working in directly from within your shell, and you can pause, edit, and execute code from within an editor. When you resume working within your shell, you will see the changes you just made in your editor.

Configuring IPython

The final “basic” information you need to know in order to begin is how to configure IPython. If you didn’t assign a different location when you ran IPython for the first time, it created an .ipython directory in your home directory. Inside the .ipython directory is a file called ipy_user_conf.py. This user file is simply a configuration file that uses Python syntax. In order to help you give IPython the look and feel that you want it to have, the config file contains a wide variety of elements that you can customize. For example, you can choose the colors used in the shell, the components of the shell prompt, and the text editor that will automatically be used use when you %edit text. We won’t go into any more detail than that here. Just know that the config file exists, and it is worth looking through to see if there are some elements you need to or want to configure.

Help with Magic Functions

As we’ve already said, IPython is incredibly powerful. One reason for this power is that there is an almost overwhelming number of built-in magic functions. Just what is a magic function? The IPython documentation says:

IPython will treat any line whose first character is a % as a special call to a ‘magic’ function. These allow you to control the behavior of IPython itself, plus a lot of system-type features. They are all prefixed with a % character, but parameters are given without parentheses or quotes.

Example: typing ‘%cd mydir’ (without the quotes) changes your working directory to ‘mydir’, if it exists.

Two of the “magic” functions can help you wade through all of this functionality and sort out what might be useful for you. The first magic help function that we’ll look at is lsmagic. lsmagic gives a listing of all the “magic” functions. Here is the output of running lsmagic:

In [1]: lsmagic
Available magic functions:
%Exit  %Pprint  %Quit  %alias  %autocall  %autoindent  %automagic  %bg
%bookmark  %cd  %clear  %color_info  %colors  %cpaste  %debug  %dhist  %dirs
%doctest_mode  %ed  %edit  %env  %exit  %hist  %history  %logoff  %logon
%logstart  %logstate  %logstop  %lsmagic  %macro  %magic  %p  %page  %pdb
%pdef  %pdoc  %pfile  %pinfo  %popd  %profile  %prun  %psearch  %psource
%pushd  %pwd  %pycat  %quickref  %quit  %r  %rehash  %rehashx  %rep  %reset
%run  %runlog  %save  %sc  %store  %sx  %system_verbose  %time  %timeit
%unalias  %upgrade  %who  %who_ls  %whos  %xmode
            
Automagic is ON, % prefix NOT needed for magic functions.

As you can see, there is an almost unwieldy number of functions for you to work with. In fact, as of this writing, there are 69 magic functions for you to use. You may find it helpful to list the magic functions like this:

In [2]: %<TAB>
%Exit            %debug           %logstop         %psearch         %save
%Pprint          %dhist           %lsmagic         %psource         %sc
%Quit            %dirs            %macro           %pushd           %store
%alias           %doctest_mode    %magic           %pwd             %sx
%autocall        %ed              %p               %pycat           %system_verbose
%autoindent      %edit            %page            %quickref        %time
%automagic       %env             %pdb             %quit            %timeit
%bg              %exit            %pdef            %r               %unalias
%bookmark        %hist            %pdoc            %rehash          %upgrade
%cd              %history         %pfile           %rehashx         %who
%clear           %logoff          %pinfo           %rep             %who_ls
%color_info      %logon           %popd            %reset           %whos
%colors          %logstart        %profile         %run             %xmode
%cpaste          %logstate        %prun            %runlog

Typing %-TAB will give you a nicer view of all 69 magic functions. The point of using the lsmagic function and %-TAB is to see a quick rundown of all the available functions when you’re looking for something specific. Or, you can use them to quickly browse through all the functions to see what is available. But unless you see a description, the list isn’t going to help you understand what each function does.

That is where magic, the next help function comes in. The name of this magic function is itself “magic.” Running magic brings up a pageable help document that the program uses for all of the built-in magic functions in IPython. The help format includes the function name, the use of the function (where applicable), and a description of the way the function works. Here is the help on the magic page function:

%page:
    Pretty print the object and display it through a pager.
    
    %page [options] OBJECT

    If no object is given, use _ (last output).
    
    Options:

      -r: page str(object), don't pretty-print it.

Depending on your pager, you can search and scroll after executing the magic function. This can come in handy if you know what function you need to look up and want to jump right to it rather than scrolling around hunting for it. The functions are arranged alphabetically, so that will help you find what you’re looking for whether you search or scroll.

You can also use another help method that we will get to later in this chapter. When you type in the name of the magic function for which you want help, followed by a question mark (?), it will give you almost the same information that %magic will give you. Here is the output of %page ?:

In [1]: %page ?
Type:           Magic function
Base Class:     <type 'instancemethod'>
String Form:    <bound method InteractiveShell.magic_page of 
                <IPython.iplib.InteractiveShell object at 0x2ac5429b8a10>>
Namespace:      IPython internal
File:           /home/jmjones/local/python/psa/lib/python2.5/site-packages/IPython/Magic.py
Definition:     %page(self, parameter_s='')
Docstring:
    Pretty print the object and display it through a pager.
    
    %page [options] OBJECT
    
    If no object is given, use _ (last output).
    
    Options:
    
      -r: page str(object), don't pretty-print it.

And here is one final piece of IPython help that is great for generating a summary of the way things work, as well as a summary of the magic functions themselves. When you type in %quickref at an IPython prompt, you’ll see a paged reference that begins this way:

IPython -- An enhanced Interactive Python - Quick Reference Card
================================================================

obj?, obj??      : Get help, or more help for object (also works as
                   ?obj, ??obj).
?foo.*abc*       : List names in 'foo' containing 'abc' in them.
%magic           : Information about IPython's 'magic' % functions.

Magic functions are prefixed by %, and typically take their arguments without
parentheses, quotes or even commas for convenience.
 
Example magic function calls:

%alias d ls -F   : 'd' is now an alias for 'ls -F'
alias d ls -F    : Works if 'alias' not a python name
alist = %alias   : Get list of aliases to 'alist'
cd /usr/share    : Obvious. cd -<tab> to choose from visited dirs.
%cd??            : See help AND source for magic %cd

System commands:
    
!cp a.txt b/     : System command escape, calls os.system()
cp a.txt b/      : after %rehashx, most system commands work without !
cp ${f}.txt $bar : Variable expansion in magics and system commands
files = !ls /usr : Capture sytem command output
files.s, files.l, files.n: "a b c", ['a','b','c'], 'a
b
c'

and ends with this:

%time:
        Time execution of a Python statement or expression.
%timeit:
        Time execution of a Python statement or expression
%unalias:
        Remove an alias
%upgrade:
         Upgrade your IPython installation
%who:
        Print all interactive variables, with some minimal formatting.
%who_ls:
        Return a sorted list of all interactive variables.
%whos:
        Like %who, but gives some extra information about each variable.
%xmode:
        Switch modes for the exception handlers.

The starting portion of %quickref is a reference to various usage scenarios for IPython. The rest of %quickref is a minisummary of each of the %magic functions. The mini-summaries in %quickref each contain the first line of the full help on each of the %magic functions found elsewhere. For example, here is the full help description of %who:

In [1]: %who ?
Type:           Magic function
Base Class:     <type 'instancemethod'>
String Form:    <bound method InteractiveShell.magic_who of 
                <IPython.iplib.InteractiveShell object at 0x2ac9f449da10>>
Namespace:      IPython internal
File:           /home/jmjones/local/python/psa/lib/python2.5/site-packages/IPython/
                Magic.py
Definition:     who(self, parameter_s='')
Docstring:
    Print all interactive variables, with some minimal formatting.

    If any arguments are given, only variables whose type matches one of
    these are printed. For example:

      %who function str

    will only list functions and strings, excluding all other types of
    variables. To find the proper type names, simply use type(var) at a
    command line to see how python prints type names. For example:

      In [1]: type('hello')
      Out[1]: <type 'str'>

    indicates that the type name for strings is 'str'.

    %who always excludes executed names loaded through your configuration
    file and things which are internal to IPython.

    This is deliberate, as typically you may load many modules and the
    purpose of %who is to show you only what you've manually defined.

The help line for %who in the %quickref is identical to the first line of the Docstring that is returned by %who ?.

Unix Shell

Working in a Unix shell certainly has its benefits (a unified approach to working through problems, a rich set of tools, a fairly terse yet simple syntax, standard I/O streams, pipes, and redirection to name a few), but it’s nice for us to be able to add a touch of Python to this old friend. IPython has some features that make bridging the two very valuable.

alias

The first feature of a Python/Unix shell bridge that we will look at is the alias magic function. With alias you can create an IPython shortcut to execute system commands. To define an alias, simply type alias followed by the system command (and any arguments for that command). For example:

In [1]: alias nss netstat -lptn

In [2]: nss
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN                        
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN     

There are a few ways to get different input into an alias. One option is the do-nothing approach. If all the extras you wanted to pass into your command can be lumped together, the do-nothing approach may be for you. For example, if you wanted to grep the results of the netstat command above for 80, you could do this:

In [3]: nss | grep 80
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN     -

This isn’t passing in extra options, but for the sake of how things are happening, it winds up being the same thing.

Next, there is the do-everything approach. It’s pretty similar to the do-nothing approach except that, by implicitly handling all arguments, you’re explicitly handling all subsequent arguments. Here is an example that shows how to treat the subsequent arguments as a single group:

In [1]: alias achoo echo "|%l|"

In [2]: achoo
||

In [3]: achoo these are args
|these are args|

This demonstrates the %l (percent sign followed by the letter “l”) syntax that is used to insert the rest of the line into an alias. In real life, you would be most likely to use this to insert everything after the alias somewhere in the middle of the implemented command that the alias is standing in for.

And here is the do-nothing example retooled to handle all arguments explicitly:

In [1]: alias nss netstat -lptn %l

In [2]: nss
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN                        
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN                        

In [3]: nss | grep 80
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN     

In this example, we really didn’t need to put the %l in there at all. If we had just left it out, we would have gotten up with the same result.

To insert different parameters throughout a command string, we would use the %s substitution string. This example shows how to run the parameters:

In [1]: alias achoo echo first: "|%s|", second: "|%s|"

In [2]: achoo foo bar
first: |foo|, second: |bar|

This can be a bit problematic, however. If you supply only one parameter and two were expected, you can expect an error:

In [3]: achoo foo
ERROR: Alias <achoo> requires 2 arguments, 1 given.
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)

On the other hand, providing more parameters than expected is safe:

In [4]: achoo foo bar bam
first: |foo|, second: |bar| bam

foo and bar are properly inserted into their respective positions, while bam is appended to the end, which is where you would expect it to be placed.

You can also persist your aliases with the %store magic function, and we will cover how to do that later in this chapter. Continuing with the previous example, we can persist the achoo alias so that the next time we open IPython, we’ll be able to use it:

In [5]: store achoo
Alias stored: achoo (2, 'echo first: "|%s|", second: "|%s|"')

In [6]:
Do you really want to exit ([y]/n)?
(psa)jmjones@dinkgutsy:code$ ipython -nobanner

In [1]: achoo one two
first: |one|, second: |two|

Shell Execute

Another, and possibly easier, way of executing a shell command is to place an exclamation point (!) in front of it:

In [1]: !netstat -lptn
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN                        
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN     

You can pass in variables to your shell commands by prefixing them with a dollar sign ($). For example:

In [1]: user = 'jmjones'

In [2]: process = 'bash'

In [3]: !ps aux | grep $user | grep $process
jmjones   5967  0.0  0.4  21368  4344 pts/0    Ss+  Apr11   0:01 bash
jmjones   6008  0.0  0.4  21340  4304 pts/1    Ss   Apr11   0:02 bash
jmjones   8298  0.0  0.4  21296  4280 pts/2    Ss+  Apr11   0:04 bash
jmjones  10184  0.0  0.5  22644  5608 pts/3    Ss+  Apr11   0:01 bash
jmjones  12035  0.0  0.4  21260  4168 pts/15   Ss   Apr15   0:00 bash
jmjones  12943  0.0  0.4  21288  4268 pts/5    Ss   Apr11   0:01 bash
jmjones  15720  0.0  0.4  21360  4268 pts/17   Ss   02:37   0:00 bash
jmjones  18589  0.1  0.4  21356  4260 pts/4    Ss+  07:04   0:00 bash
jmjones  18661  0.0  0.0    320    16 pts/15   R+   07:06   0:00 grep bash
jmjones  27705  0.0  0.4  21384  4312 pts/7    Ss+  Apr12   0:01 bash
jmjones  32010  0.0  0.4  21252  4172 pts/6    Ss+  Apr12   0:00 bash

This listed all bash sessions belonging to jmjones.

Here’s an example of the way to store the result of a ! command:

In [4]: l = !ps aux | grep $user | grep $process

In [5]: l

Out[5]: SList (.p, .n, .l, .s, .grep(), .fields() available). Value:
0: jmjones   5967  0.0  0.4  21368  4344 pts/0    Ss+  Apr11   0:01 bash
1: jmjones   6008  0.0  0.4  21340  4304 pts/1    Ss   Apr11   0:02 bash
2: jmjones   8298  0.0  0.4  21296  4280 pts/2    Ss+  Apr11   0:04 bash
3: jmjones  10184  0.0  0.5  22644  5608 pts/3    Ss+  Apr11   0:01 bash
4: jmjones  12035  0.0  0.4  21260  4168 pts/15   Ss   Apr15   0:00 bash
5: jmjones  12943  0.0  0.4  21288  4268 pts/5    Ss   Apr11   0:01 bash
6: jmjones  15720  0.0  0.4  21360  4268 pts/17   Ss   02:37   0:00 bash
7: jmjones  18589  0.0  0.4  21356  4260 pts/4    Ss+  07:04   0:00 bash
8: jmjones  27705  0.0  0.4  21384  4312 pts/7    Ss+  Apr12   0:01 bash
9: jmjones  32010  0.0  0.4  21252  4172 pts/6    Ss+  Apr12   0:00 bash

You may notice that the output stored in the variable l is different from the output in the previous example. That’s because the variable l contains a list-like object, while the previous example showed the raw output from the command. We’ll discuss that list-like object later in String Processing.”

An alternative to ! is !!, except that you can’t store the result in a variable as you are running it, !! does the same thing that ! does. But you can access it with the _ or _[0-9]* notation that we’ll discuss later in History results.”

Programming a quick ! or !! before a shell command is definitely less work than creating an alias, but you may be better off creating aliases in some cases and using the ! or !! in others. For example, if you are typing in a command you expect to execute all the time, create an alias or macro. If this is a one time or infrequent occurrence, then just use ! or !!.

rehash

There is another option for aliasing and/or executing shell commands from IPython: rehashing. Technically, this is creating an alias for shell commands, but it doesn’t really feel like that is what you’re doing. The rehash “magic” function updates the “alias table” with everything that is on your PATH. You may be asking, “What is the alias table?” When you create an alias, IPython has to map the alias name to the shell command with which you wanted it to be associated. The alias table is where that mapping occurs.

Note

The preferred way of rehashing the alias table is to use the rehashx magic function rather than rehash. We will present both to demonstrate the ways they work, and then we will describe their differences.

IPython exposes a number of variables that you have access to when running IPython, such as In and Out, which we saw earlier. One of the variables that IPython exposes is __IP, which is actually the interactive shell object. An attribute named alias_table hangs on that object. This is where the mapping of alias names to shell commands takes place. We can look at this mapping in the same way we would look at any other variable:

In [1]: __IP.alias_table

Out[1]: 
{'cat': (0, 'cat'),
 'clear': (0, 'clear'),
 'cp': (0, 'cp -i'),
 'lc': (0, 'ls -F -o --color'),
 'ldir': (0, 'ls -F -o --color %l | grep /$'),
 'less': (0, 'less'),
 'lf': (0, 'ls -F -o --color %l | grep ^-'),
 'lk': (0, 'ls -F -o --color %l | grep ^l'),
 'll': (0, 'ls -lF'),
 'lrt': (0, 'ls -lart'),
 'ls': (0, 'ls -F'),
 'lx': (0, 'ls -F -o --color %l | grep ^-..x'),
 'mkdir': (0, 'mkdir'),
 'mv': (0, 'mv -i'),
 'rm': (0, 'rm -i'),
 'rmdir': (0, 'rmdir')}

It looks like a dictionary:

In [2]: type(__IP.alias_table)

Out[2]: <type 'dict'>

Looks can be deceiving, but they’re not this time.

Right now, this dictionary has 16 entries:

In [3]: len(__IP.alias_table)

Out[3]: 16

After we rehash, this mapping gets much larger:

In [4]: rehash

In [5]: len(__IP.alias_table)

Out[5]: 2314

Let’s look for something that wasn’t there before, but should be there now—the transcode utility should be in the alias table now:

In [6]: __IP.alias_table['transcode']

Out[6]: (0, 'transcode')

Note

When you see a variable or attribute name that begins with a double underscore (__), it usually means that the author of that code doesn’t want you to change. We’re accessing __IP here, but it’s only to show you the internals structure. If we wanted to access the official API for IPython, we would use the _ip object that is accessible at the IPython prompt.

rehashx

Excepting that rehashx looks for things on your PATH that it thinks are executable to add to the alias table, rehashx is similar to rehash. So, when we start a new IPython shell and rehashx, we would expect the alias table to be the same size as or smaller than the result of rehash:

In [1]: rehashx

In [2]: len(__IP.alias_table)

Out[2]: 2307

Interesting; rehashx produces an alias table with seven fewer items than rehash. Here are the seven differences:

In [3]: from sets import Set

In [4]: rehashx_set = Set(__IP.alias_table.keys())

In [5]: rehash

In [6]: rehash_set = Set(__IP.alias_table.keys())

In [7]: rehash_set - rehashx_set

Out[7]: Set(['fusermount', 'rmmod.modutils', 'modprobe.modutils', 'kallsyms', 'ksyms', /
       'lsmod.modutils', 'X11'])

And if we look to see why rmmod.modutils didn’t show up when we ran rehashx but did show up when we ran for rehash, here is what we find:

jmjones@dinkgutsy:Music$ slocate rmmod.modutils
/sbin/rmmod.modutils
jmjones@dinkgutsy:Music$ ls -l /sbin/rmmod.modutils 
lrwxrwxrwx 1 root root 15 2007-12-07 10:34 /sbin/rmmod.modutils -> insmod.modutils
jmjones@dinkgutsy:Music$ ls -l /sbin/insmod.modutils
ls: /sbin/insmod.modutils: No such file or directory

So, you can see that rmmod.modutils is a link to insmod.modutils, and insmod.modutils doesn’t exist.

cd

If you have the standard Python shell, you may have noticed that it can be hard to determine which directory you’re in. You can use os.chdir() to change the directory, but that isn’t very convenient. You could also get the current directory via os.getcwd(), but that’s not terribly convenient either. Since you are executing Python commands rather than shell commands with the standard Python shell, maybe it isn’t that big of a problem, but when you are using IPython and have easy access to the system shell, having comparably easy access to directory navigation is critical.

Enter cd magic. It seems like we’re making a bigger deal out of this than it warrants: this isn’t a revolutionary concept; it’s not all that difficult. But just imagine if it were missing. That would be painful.

In IPython, cd works mostly as it does in Bash. The primary usage is cd directory_name. That works as you would expect it to from your Bash experience. With no arguments, cd takes you to your home directory. With a space and hyphen as an argument, cd - takes you to your previous directory. There are three additional options that Bash cd doesn’t give you.

The first is the -q, or quiet, option. Without this option, IPython will output the directory into which you just changed. The following example shows the ways to change a directory both with and without the -q option:

In [1]: cd /tmp
/tmp

In [2]: pwd

Out[2]: '/tmp'

In [3]: cd -
/home/jmjones

In [4]: cd -q /tmp

In [5]: pwd

Out[5]: '/tmp'

Using the -q prevented IPython from outputting the /tmp directory we had gone into.

Another feature that IPython’s cd includes is the ability to go to defined bookmarks. (We’ll explain how to create bookmarks soon.) Here is an example of how to change a directory for which you have created a bookmark:

In [1]: cd -b t
(bookmark:t) -> /tmp
/tmp

This example assumes that we have bookmarked /tmp the name t. The formal syntax to change to a bookmarked directory is cd -b bookmark_name, but, if a bookmark of bookmark_name is defined and there is not a directory called bookmark_name in the current directory, the -b flag is optional; IPython can figure out that you are intending to go into a bookmarked directory.

The final extra feature that cd offers in IPython is the ability to change into a specific directory given a history of directories that have been visited. The following is an example that makes use of this directory history:

0: /home/jmjones
1: /home/jmjones/local/Videos
2: /home/jmjones/local/Music
3: /home/jmjones/local/downloads
4: /home/jmjones/local/Pictures
5: /home/jmjones/local/Projects
6: /home/jmjones/local/tmp
7: /tmp
8: /home/jmjones

In [2]: cd -6
/home/jmjones/local/tmp

First, you see there is a list of all the directories in our directory history. We’ll get to where it came from in a moment. Next, we pass the numerical argument –6. This tells IPython that we want to go to the item in our history marked “6”, or /home/jmjones/local/tmp. Finally, you can see that these are now in /home/jmjones/local/tmp.

bookmark

We just showed you how to use a cd option to move into a bookmarked directory. Now we’ll show you how to create and manage your bookmarks. It deserves mentioning that bookmarks persist across IPython sessions. If you exit IPython and start it back up, your bookmarks will still be there. There are two ways to create bookmarks. Here is the first way:

In [1]: cd /tmp
/tmp

In [2]: bookmark t

By typing in bookmark t while we’re in /tmp, a bookmark named t is created and pointing at /tmp. The next way to create a bookmark requires typing one more word:

In [3]: bookmark muzak /home/jmjones/local/Music

Here, we created a bookmark named muzak that points to a local music directory. The first argument is the bookmark’s name, while the second is the directory the bookmark points to.

The -l option tells IPython to get the list of bookmarks, of which we have only two. Now, let’s see a list of all our bookmarks:

In [4]: bookmark -l
Current bookmarks:
muzak -> /home/jmjones/local/Music
t     -> /tmp

There are two options for removing bookmarks: remove them all, or remove one at a time. In this example, we’ll create a new bookmark, remove it, and then remove all in the following example:

In [5]: bookmark ulb /usr/local/bin

In [6]: bookmark -l
Current bookmarks:
muzak -> /home/jmjones/local/Music
t     -> /tmp
ulb   -> /usr/local/bin

In [7]: bookmark -d ulb

In [8]: bookmark -l
Current bookmarks:
muzak -> /home/jmjones/local/Music
t     -> /tmp

An alternative to using bookmark -l is to use cd -b:

In [9]: cd -b<TAB>
muzak  t      txt

And after a few backspaces, we’ll continue where we left off:

In [9]: bookmark -r

In [10]: bookmark -l
Current bookmarks:

We created a bookmark named ulb pointing to /usr/local/bin. Then, we deleted it with the -d bookmark_name option for bookmark. Finally, we deleted all bookmarks with the -r option.

dhist

In the cd example above, we show a list of the directories we had visited. Now we’ll show you how to view that list. The magic command is dhist, which not only saves the session list, but also saves the list of directories across IPython sessions. Here is what happens when you run dhist with no arguments:

In [1]: dhist
Directory history (kept in _dh)
0: /home/jmjones
1: /home/jmjones/local/Videos
2: /home/jmjones/local/Music
3: /home/jmjones/local/downloads
4: /home/jmjones/local/Pictures
5: /home/jmjones/local/Projects
6: /home/jmjones/local/tmp
7: /tmp
8: /home/jmjones
9: /home/jmjones/local/tmp
10: /tmp

A quick way to access directory history is to use cd -<TAB> like this:

In [1]: cd -
-00 [/home/jmjones]                  -06 [/home/jmjones/local/tmp]
-01 [/home/jmjones/local/Videos]     -07 [/tmp]
-02 [/home/jmjones/local/Music]      -08 [/home/jmjones]
-03 [/home/jmjones/local/downloads]  -09 [/home/jmjones/local/tmp]
-04 [/home/jmjones/local/Pictures]   -10 [/tmp]
-05 [/home/jmjones/local/Projects]

There are two options that make dhist more flexible than cd -<TAB>. The first is that you can provide a number to specify how many directories should be displayed. To specify that we want to see only the last five directories that were visited, we would input the following:

In [2]: dhist 5
Directory history (kept in _dh)
6: /home/jmjones/local/tmp
7: /tmp
8: /home/jmjones
9: /home/jmjones/local/tmp
10: /tmp

The second option is that you can specify a range of directories that were visited. For example, to view from the third through the sixth directories visited, we would enter the following:

In [3]: dhist 3 7
Directory history (kept in _dh)
3: /home/jmjones/local/downloads
4: /home/jmjones/local/Pictures
5: /home/jmjones/local/Projects
6: /home/jmjones/local/tmp

Notice that the ending range entry is noninclusive, so you have to indicate the directory immediately following the final directory you want to see.

pwd

A simple but nearly necessary function for directory navigation, pwd simply tells you what your current directory is. Here is an example:

In [1]: cd /tmp
/tmp

In [2]: pwd

Out[2]: '/tmp'

Variable Expansion

The previous eight or so IPython features are definitely helpful and necessary, but the next three features will give great joy to power users. The first of these is variable expansion. Up to this point, we’ve mostly kept shell stuff with shell stuff and Python stuff with Python stuff. But now, we’re going to cross the line and mingle the two of them. That is, we’re going to take a value that we get from Python and hand it to the shell:

In [1]: for i in range(10):
   ...:     !date > ${i}.txt
   ...:     
   ...:     

In [2]: ls
0.txt  1.txt  2.txt  3.txt  4.txt  5.txt  6.txt  7.txt  8.txt  9.txt

In [3]: !cat 0.txt
Sat Mar  8 07:40:05 EST 2008

This example isn’t all that realistic. It is unlikely that you will want to create 10 text files that all contain the date. But the example does show how to mingle Python code and shell code. We iterated over a list created by the range() function and stored the current item in the list in variable i. For each time through the iteration, we use the shell execution ! notation to call out to the date command-line system utility. Notice that the syntax we use for calling date is identical to the way we would call it if we had defined a shell variable i. So, the date utility is called, and the output is redirected to the file {current list item}.txt. We list the files after creating them and even cat one out to see that it contains something that looks like a date.

You can pass any kind of value you can come up with in Python into your system shell. Whether it is in a database or in a pickle file, generated by computation, an XMLRPC service, or data you extract from a text file, you can pull it in with Python and then pass it to the system shell with the ! execution trick.

String Processing

Another incredibly powerful feature that IPython offers is the ability to string process the system shell command output. Suppose we want to see the PIDs of all the processes belonging to the user jmjones. We could do that by inputting the following:

ps aux | awk '{if ($1 == "jmjones") print $2}'

This is pretty tight, succinct, and legible. But let’s tackle the same task using IPython. First, let’s grab the output from an unfiltered ps aux:

In [1]: ps = !ps aux

In [2]:

The result of calling ps aux, which is stored in the variable ps, is a list-like structure whose elements are the lines that were returned from the shell system call. It is list-like, in this case, because we mean that it inherits from the built-in list type, so it supports all the methods of that type. So, if you have a function or method that expects a list, you can pass one of these result objects to it as well. In addition to supporting the standard list methods, it also supports a couple of very interesting methods and one attribute that will come in handy. Just to show what the “interesting methods” do, we’ll divert from our end goal of finding all processes owned by jmjones for just a moment. The first “interesting method” we’ll look at is the grep() method. This is basically a simple filter that determines which lines of the output to keep and which to leave off. To see if any of the lines in the output match lighttpd, we would input the following:

In [2]: ps.grep('lighttpd')

Out[2]: SList (.p, .n, .l, .s, .grep(), .fields() available). Value:
0: www-data  4905  0.0  0.1........0:00 /usr/sbin/lighttpd -f /etc/lighttpd/l

We called the grep() method and passed it the regular expression 'lighttpd'. Remember, regular expressions passed to grep() are case-insensitive. The result of this grep() call was a line of output that showed that there was a positive match for the 'lighttpd' regular expression. To see all records except those that match a certain regular expression, we would do something more like this:

In [3]: ps.grep('Mar07', prune=True)

Out[3]: SList (.p, .n, .l, .s, .grep(), .fields() available). Value:
0: USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
1: jmjones  19301  0.0  0.4  21364  4272 pts/2    Ss+  03:58   0:00 bash
2: jmjones  21340  0.0  0.9 202484 10184 pts/3    Sl+  07:00   0:06 vim ipytho
3: jmjones  23024  0.0  1.1  81480 11600 pts/4    S+   08:58   0:00 /home/jmjo
4: jmjones  23025  0.0  0.0      0     0 pts/4    Z+   08:59   0:00 [sh] <defu
5: jmjones  23373  5.4  1.0  81160 11196 pts/0    R+   09:20   0:00 /home/jmjo
6: jmjones  23374  0.0  0.0   3908   532 pts/0    R+   09:20   0:00 /bin/sh -c
7: jmjones  23375  0.0  0.1  15024  1056 pts/0    R+   09:20   0:00 ps aux

We passed in the regular expression 'Mar07' to the grep() method and found that most of the processes on this system were started on March 7, so we decided that we wanted to see all processes not started on March 7. In order to exclude all 'Mar07' entries, we had to pass in another argument to grep(), this time a keyword argument: prune=True. This keyword argument tells IPython, “Any records you find that match the stated regular expression—throw them out.” And as you can see, there are no records that match the 'Mar07' regex.

Callbacks can also be used with grep(). This just means that grep() will take a function as an argument and call that function. It will pass the function to the item in the list that it is working on. If the function returns True on that item, the item is included in the filter set. For example, we could do a directory listing and filter out only files or only directories:

In [1]: import os

In [2]: file_list = !ls

In [3]: file_list

Out[3]: SList (.p, .n, .l, .s, .grep(), .fields() available). Value:
0: ch01.xml
1: code
2: ipython.pdf
3: ipython.xml

This directory listing shows four “files.” We can’t tell from this list which are files and which are directories, but if we filter using the os.path.isfile() test, we can see which ones are files:

In [4]: file_list.grep(os.path.isfile)

Out[4]: SList (.p, .n, .l, .s, .grep(), .fields() available). Value:
0: ch01.xml
1: ipython.pdf
2: ipython.xml

This left out the “file” named code, so code must not be a file at all. Let’s filter for directories:

In [5]: file_list.grep(os.path.isdir)

Out[5]: SList (.p, .n, .l, .s, .grep(), .fields() available). Value:
0: code

Now that we see that code is, in fact, a directory, another interesting method is fields(). After (or, we guess, even before) you filter your result set down to the desired level of specificity, you can display exactly the fields that you want to display. Let’s take the non-Mar07 example that we just walked through and output the user, pid, and start columns:

In [4]: ps.grep('Mar07', prune=True).fields(0, 1, 8)

Out[4]: SList (.p, .n, .l, .s, .grep(), .fields() available). Value:
0: USER PID START
1: jmjones 19301 03:58
2: jmjones 21340 07:00
3: jmjones 23024 08:58
4: jmjones 23025 08:59
5: jmjones 23373 09:20
6: jmjones 23374 09:20
7: jmjones 23375 09:20

First, notice that whatever it is that fields() does, we’re doing it to the result of the grep() method call. We are able to do this because grep() returns an object of the same type as the ps object that we started with. And fields() itself returns the same object type as grep(). Since that is the case, you can chain grep() and fields() calls together. Now, on to what is going on here. The fields() method takes an indefinite number of arguments, and these arguments are expected to be the “columns” from the output, if the output lines were split on whitespace. You can think of this very much like the default splitting that awk does to lines of text. In this case, we called fields() to view columns 0, 1, and 8. These are, respectively, USERNAME, PID, and STARTTIME.

Now, back to showing the PIDs of all processes belonging to jmjones:

In [5]: ps.fields(0, 1).grep('jmjones').fields(1)

Out[5]: SList (.p, .n, .l, .s, .grep(), .fields() available). Value:
0: 5385
1: 5388
2: 5423
3: 5425
4: 5429
5: 5431
6: 5437
7: 5440
8: 5444
<continues on...>

This example first trims the result set back to only two columns, 0 and 1, which are the username and PID, respectively. Then, we take that narrower result set and grep() for 'jmjones'. Finally, we take that filtered result set and request the second field by calling fields(1). (Remember, lists start at zero.)

The final piece of string processing that we want to showcase is the s attribute of the object trying to directly access your process list. This object is probably not going to give you the results you were looking for. In order to get the system shell to work with your output, use the s attribute on your process list object:

In [6]: ps.fields(0, 1).grep('jmjones').fields(1).s

Out[6]: '5385 5388 5423 5425 5429 5431 5437 5440 5444 5452 5454 5457 5458 5468 
5470 5478 5480 5483 5489 5562 5568 5593 5595 5597 5598 5618 5621 5623 5628 5632 
5640 5740 5742 5808 5838 12707 12913 14391 14785 19301 21340 23024 23025 23373 
23374 23375'

The s attribute gives us a nice space-separated string of PIDs that we can work with in a system shell. We wanted to, we could store that stringified list in a variable called pids and do something like kill $pids from within IPython. But that would send a SIGTERM to every process owned by jmjones, and it would kill his text editor and his IPython sessions.

Earlier, we demonstrated that we could accomplish the stated goals for our IPython script with the following awk one-liner:

ps aux | awk '{if ($1 == "jmjones") print $2}'

We will be ready to accomplish this goal after we’ve introduced one more concept. The grep() method takes a final optional parameter called field. If we specify a field parameter, the search criteria has to match that field in order for that item to be included in the result set:

In [1]: ps = !ps aux

In [2]: ps.grep('jmjones', field=0)

Out[2]: SList (.p, .n, .l, .s, .grep(), .fields() available). Value:
0: jmjones   5361  0.0  0.1  46412  1828 ?        SL   Apr11   
  0:00 /usr/bin/gnome-keyring-daemon -d
1: jmjones   5364  0.0  1.4 214948 14552 ?        Ssl  Apr11   
  0:03 x-session-manager
....
53: jmjones  32425  0.0  0.0   3908   584 ?        S    Apr15  
   0:00 /bin/sh /usr/lib/firefox/run-mozilla.
54: jmjones  32429  0.1  8.6 603780 88656 ?        Sl   Apr15   
  2:38 /usr/lib/firefox/firefox-bin

This matched the exact rows that we wanted, but printed out the whole row. To get at just the PID, we’ll have to do something like this:

In [3]: ps.grep('jmjones', field=0).fields(1)

Out[3]: SList (.p, .n, .l, .s, .grep(), .fields() available). Value:
0: 5361
1: 5364
....
53: 32425
54: 32429

And with that, we are able to meet the goal of performing that specific awk filter.

sh Profile

One IPython concept that we haven’t described yet is a profile. A profile is simply a set of configuration data that is loaded when you start IPython. You can customize a number of profiles to make IPython perform in different ways depending on a session’s needs. To invoke a specific profile, use the -p command-line option and specify the profile you’d like to use.

The sh, or shell, profile is one of the built-in profiles for IPython. The sh profile sets some configuration items so that IPython becomes a more friendly system shell. Two examples of configuration values that are different from the standard IPython profile are that sh displays the current directory and it rehashes your PATH so that you have instant access to all of the same executables that you would have in, say, Bash.

In addition to setting certain configuration values, the sh profile also enables a few shell-helpful extensions. For example, it enables the envpersist extension. The envpersist extension allows you to modify various environment variables easily and persistently for your IPython sh profile, and you don’t have to update a .bash_profile or .bashrc.

Here, is what our PATH looks like:

jmjones@dinkgutsy:tmp$ ipython -p sh
IPython 0.8.3.bzr.r96   [on Py 2.5.1]
[~/tmp]|2> import os
[~/tmp]|3> os.environ['PATH']
       <3> '/home/jmjones/local/python/psa/bin:
       /home/jmjones/apps/lb/bin:/home/jmjones/bin:
       /usr/local/sbin:/usr/local/bin:/usr/sbin:
       /usr/bin:/sbin:/bin:/usr/games'

Now we add :/appended to the end of our current PATH:

[~/tmp]|4> env PATH+=:/appended
PATH after append = /home/jmjones/local/python/psa/bin:
/home/jmjones/apps/lb/bin:/home/jmjones/bin:
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:
/sbin:/bin:/usr/games:/appended

and /prepended: to the beginning of our current PATH:

[~/tmp]|5> env PATH-=/prepended:
PATH after prepend = /prepended:/home/jmjones/local/python/psa/bin:
/home/jmjones/apps/lb/bin:/home/jmjones/bin:/usr/local/sbin:
/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/appended

This shows the PATH environment variable using os.environ:

[~/tmp]|6> os.environ['PATH']
       <6> '/prepended:/home/jmjones/local/python/psa/bin:
       /home/jmjones/apps/lb/bin:/home/jmjones/bin:
       /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:
       /bin:/usr/games:/appended'

Now we’ll exit our IPython shell:

[~/tmp]|7>
Do you really want to exit ([y]/n)?
jmjones@dinkgutsy:tmp$

Finally, we’ll open a new IPython shell to see what the PATH environment variable shows:

jmjones@dinkgutsy:tmp$ ipython -p sh
IPython 0.8.3.bzr.r96   [on Py 2.5.1]
[~/tmp]|2> import os
[~/tmp]|3> os.environ['PATH']
       <3> '/prepended:/home/jmjones/local/python/psa/bin:
       /home/jmjones/apps/lb/bin:/home/jmjones/bin:/usr/local/sbin:
       /usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/appended'

Interestingly, it shows our prepended and appended values, even though we didn’t update any profile scripts. It persisted the change to PATH without any additional work on our part. Now let’s display all persistent changes to environment variables:

[~/tmp]|4> env -p
       <4> {'add': [('PATH', ':/appended')], 'pre': [('PATH', '/prepended:')], 'set': {}}

We can delete any persistent changes to PATH:

[~/tmp]|5> env -d PATH
Forgot 'PATH' (for next session)

and we can check to see the value of PATH:

[~/tmp]|6> os.environ['PATH']
       <6> '/prepended:/home/jmjones/local/python/psa/bin:/home/jmjones/apps/lb/bin:
       /home/jmjones/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:
       /sbin:/bin:/usr/games:/appended'

Even after we’ve told IPython to remove the persistent entries for PATH, they are still there. But that makes sense. That just means that IPython should remove the directive to persist those entries. Note that the process started with certain values in an environment variable will retain those values unless something changes them. The next time the IPython shell starts, things should be different:

[~/tmp]|7>
Do you really want to exit ([y]/n)?
jmjones@dinkgutsy:tmp$ ipython -p sh
IPython 0.8.3.bzr.r96   [on Py 2.5.1]
[~/tmp]|2> import os
[~/tmp]|3> os.environ['PATH']
       <3> '/home/jmjones/local/python/psa/bin:/home/jmjones/apps/lb/bin:
       /home/jmjones/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:
       /sbin:/bin:/usr/games'

And, just as we would expect, this is back to what it was before we started making changes to our PATH.

One other useful feature in the sh profile is mglob. mglob has a simpler syntax for a lot of common uses. For example, to find all of the .py files in the Django project, we could just do this:

[django/trunk]|3> mglob rec:*py
              <3> SList (.p, .n, .l, .s, .grep(), .fields() available). Value:
0: ./setup.py
1: ./examples/urls.py
2: ./examples/manage.py
3: ./examples/settings.py
4: ./examples/views.py
...
1103: ./django/conf/project_template/urls.py
1104: ./django/conf/project_template/manage.py
1105: ./django/conf/project_template/settings.py
1106: ./django/conf/project_template/__init__.py
1107: ./docs/conf.py
[django/trunk]|4>

The rec directive simply says to look recursively for the following pattern. In this case, the pattern is *py. To show all directories in the Django root directory, we would issue a command like this:

[django/trunk]|3> mglob dir:*
              <3> SList (.p, .n, .l, .s, .grep(), .fields() available).
              Value:
              0: examples
              1: tests
              2: extras
              3: build
              4: django
              5: docs
              6: scripts
              </3>

The mglob command returns a Python list-like object, so anything we can do in Python, we can do to this list of returned files or folders.

This was just a taste of how the sh behaves. There are some sh profile features and feature options that we didn’t cover.

Information Gathering

IPython is much more than just a shell in which you can actively get work done. It also works as a tool to gather up all sorts of information about the code and objects you are working with. It can be such an asset in digging up information that it can feel like a forensic or investigatory tool. This section will outline a number of the features that can help you gather information.

page

If an object you are dealing with has too much of a representation to fit on one screen, you may want to try the magic page function. You can use page to pretty print your object and run it through a pager. The default pager on many systems is less, but yours might use something different. Standard usage is as follows:

In [1]: p = !ps aux
 ==
['USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND',
 'root         1  0.0  0.1   5116  1964 ?        Ss   Mar07   0:00 /sbin/init',
< ... trimmed result ... >
In [2]: page p
['USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND',
 'root         1  0.0  0.1   5116  1964 ?        Ss   Mar07   0:00 /sbin/init',
< ... trimmed result ... >

Here, we stored the result of the system shell command ps aux in the variable p. Then, we called page and passed the process result object to it. The page function then opened less.

There is one option for page: -r. This option tells page not to pretty print the object, but to run its string representation (result of str()) through the pager instead. For our process output object, that would look like this:

In [3]: page -r p
ilus-cd-burner/mapping-d', 'jmjones   5568  0.0  1.0 232004 10608 ?        S    
Mar07   0:00 /usr/lib/gnome-applets/trashapplet --', 'jmjones   5593  0.0  0.9 
188996 10076 ?        S    Mar07   0:00 /usr/lib/gnome-applets/battstat-apple', 
'jmjones   5595  0.0  2.8 402148 29412 ?        S    Mar07   0:01 p
< ... trimmed result ... >

This non-pretty-printed result is not pretty, indeed. We recommend starting out with the pretty printer and then working from there.

pdef

The magic pdef function prints the definition headers or the function signature of any callable object. In this example, we create our own function with a docstring and return statement:

In [1]: def myfunc(a, b, c, d):
   ...:     '''return something by using a, b, c, d to do something'''
   ...:     return a, b, c, d
   ...: 

In [2]: pdef myfunc
 myfunc(a, b, c, d)

The pdef function ignored our docstring and return statement, but printed out the function signature portion of the function. You can use this on any callable function. This function even works if the source code is not available as long as it has access to either the .pyc file or the egg.

pdoc

The pdoc function prints the docstring of the function you pass to it. Here, we run the same myfunc() function that we used in the pdef example through pdoc:

In [3]: pdoc myfunc
Class Docstring:
    return something by using a, b, c, d to do something
Calling Docstring:
    x.__call__(...) <==> x(...)

This one is pretty self-explanatory.

pfile

The pfile function will run the file that contains an object through the pager if it can find the containing file:

In [1]: import os

In [2]: pfile os

r"""OS routines for Mac, NT, or Posix depending on what system we're on.

This exports:
  - all functions from posix, nt, os2, mac, or ce, e.g. unlink, stat, etc.

< ... trimmed result ... >

This opened the os module and ran it through less. This can definitely be handy if you are trying to understand the reason a piece of code is behaving in a particular way. It will not work if the only access to the file is an egg or a .pyc file.

Note

You can see the same information from the ?? operator that you can from the magic functions %pdef, %pdoc, and %pfile. The preferred method is ??.

pinfo

The pinfo function and related utilities have become such a convenience for us that it’s hard to imagine not having them. The pinfo function provides information such as type, base class, namespace, and docstring. If we have a module that contains:

#!/usr/bin/env python

class Foo:
    """my Foo class"""
    def __init__(self):
        pass

class Bar:
    """my Bar class"""
    def __init__(self):
        pass

class Bam:
    """my Bam class"""
    def __init__(self):
        pass

then we can request information from the module itself:

In [1]: import some_module

In [2]: pinfo some_module
Type:           module
Base Class:     <type 'module'>
String Form:    <module 'some_module' from 'some_module.py'>
Namespace:      Interactive
File:           /home/jmjones/code/some_module.py
Docstring:
    <no docstring>

We can request information from a class in the module:

In [3]: pinfo some_module.Foo
Type:           classobj
String Form:    some_module.Foo
Namespace:      Interactive
File:           /home/jmjones/code/some_module.py
Docstring:
    my Foo class

Constructor information:
Definition:     some_module.Foo(self)

We can request information from an instance of one of those classes:

In [4]: f = some_module.Foo()

In [5]: pinfo f
Type:           instance
Base Class:     some_module.Foo
String Form:    <some_module.Foo instance at 0x86e9e0>
Namespace:      Interactive
Docstring:
    my Foo class

A question mark (?) preceeding or following an object name provides the same functionality as pinfo:

In [6]: ? f
Type:           instance
Base Class:     some_module.Foo
String Form:    <some_module.Foo instance at 0x86e9e0>
Namespace:      Interactive
Docstring:
    my Foo class


In [7]: f ?
Type:           instance
Base Class:     some_module.Foo
String Form:    <some_module.Foo instance at 0x86e9e0>
Namespace:      Interactive
Docstring:
    my Foo class

But two question marks (??) preceeding or following an object name provides us with even more information:

In [8]: some_module.Foo ??
Type:           classobj
String Form:    some_module.Foo
Namespace:      Interactive
File:           /home/jmjones/code/some_module.py
Source:
class Foo:
    """my Foo class"""
    def __init__(self):
        pass
Constructor information:
Definition:     some_module.Foo(self)

The ?? notation provides us with all the information that pinfo provided us plus the source code for the requested object. Because we only asked for the class, ?? gave us the source code for this class rather than for the whole file. This is one of the features of IPython that we find ourselves using more than nearly any other.

psource

The psource function shows the source code for the element you define, whether that’s a module or something in a module, like a class or function. It runs the source code through a pager in order to display it. Here is an example of psource for a module:

In [1]: import some_other_module

In [2]: psource some_other_module
#!/usr/bin/env python

class Foo:
    """my Foo class"""
    def __init__(self):
        pass

class Bar:
    """my Bar class"""
    def __init__(self):
        pass

class Bam:
    """my Bam class"""
    def __init__(self):
        pass

def baz():
    """my baz function"""
    return None

Here is an example of psource for a class in a module:

In [3]: psource some_other_module.Foo
class Foo:
    """my Foo class"""
    def __init__(self):
        pass

and here is an example of psource for a function in a module:

In [4]: psource some_other_module.baz
def baz():
    """my baz function"""
    return None

psearch

The psearch magic function will look for Python objects by name, with the aid of wildcards. We’ll just briefly describe the psearch function here and if you want to know more, you can find documentation on the magic functions by typing magic at an IPython prompt, and then searching within the alphabetical list for psearch.

Let’s start by declaring the following objects:

In [1]: a = 1

In [2]: aa = "one"

In [3]: b = 2

In [4]: bb = "two"

In [5]: c = 3

In [6]: cc = "three"

We can search for all of the objects starting with a, b, or c as follows:

In [7]: psearch a*
a
aa
abs
all
any
apply

In [8]: psearch b*
b
basestring
bb
bool
buffer

In [9]: psearch c*
c
callable
cc
chr
classmethod
cmp
coerce
compile
complex
copyright
credits

Notice all the objects that were found in addition to a, aa, b, bb, c, cc; those are built-ins.

There is a quick and dirty alternative to using psearch: the ? operator. Here’s an example:

In [2]: import os

In [3]: psearch os.li*
os.linesep
os.link
os.listdir

In [4]: os.li*?
os.linesep
os.link
os.listdir

Instead of psearch, we were able to use *?.

There is an option to search -s or exclude searching -e a given namespace built-in to psearch. Namespaces include builtin, user, user_global, internal, and alias. By default, psearch searches builtin and user. To explicitly search user only, we would pass a -e builtin psearch option to exclude searching the builtin namespace. This is a little counterintuitive, but it makes an odd sort of sense. The default search path for psearch is builtin and user, so if we specify a -s user, searching builtin and user would still be what we’re asking it to do. In this example, the search is run again; notice that these results exclude the built-ins:

In [10]: psearch -e builtin a*
a
aa

In [11]: psearch -e builtin b*
b
bb

In [12]: psearch -e builtin c*
c
cc

The psearch function also allows searching for specific types of objects. Here, we search the user namespace for integers:

In [13]: psearch -e builtin * int
a
b
c

and here we search for strings:

In [14]: psearch -e builtin * string
__
___
__name__
aa
bb
cc

The __ and ___ objects that were found are IPython shorthand for previous return results. The __name__ object is a special variable that denotes the name of the module. If __name__ is '__main__', it means that the module is being run from the interpreter rather than being imported from another module.

who

IPython provides a number of facilities for listing all interactive objects. The first of these is the who function. Here is the previous example, including the a, aa, b, bb, c, cc variables, with the addition of the magic who function:

In [15]: who
a       aa      b       bb      c       cc

That’s pretty straightforward; it returns a simple listing of all interactively defined objects. You can also use who to filter on types. For example:

In [16]: who int
a       b       c

In [17]: who str
aa      bb      cc

who_ls

Except that it returns a list rather than printing the names of the matching variables, who_ls is similar to who. Here is an example of the who_ls function with no arguments:

In [18]: who_ls

Out[18]: ['a', 'aa', 'b', 'bb', 'c', 'cc']

and here is an example of filtering based on the types of objects:

In [19]: who_ls int

Out[19]: ['a', 'b', 'c']

In [20]: who_ls str

Out[20]: ['aa', 'bb', 'cc']

Since who_ls returns a list of the names, you can access the list of names using the _ variable, which just means “the last output.” Here is the way to iterate the last returned list of matching variable names:

In [21]: for n in _:
   ....:     print n
   ....:     
   ....:     
aa
bb
cc

whos

The whos function is similar to the who function except that whos prints out information that who doesn’t. Here is an example of the whos function used with no command-line arguments:

In [22]: whos
Variable   Type    Data/Info
----------------------------
a          int     1
aa         str     one
b          int     2
bb         str     two
c          int     3
cc         str     three
n          str     cc

And as we can with who, we can filter on type:

In [23]: whos int
Variable   Type    Data/Info
----------------------------
a          int     1
b          int     2
c          int     3

In [24]: whos str
Variable   Type    Data/Info
----------------------------
aa         str     one
bb         str     two
cc         str     three
n          str     cc

History

There are two ways to gain access to your history of typed-in commands in IPython. The first is readline-based; the second is the hist magic function.

Readline support

In IPython, you have access to all the cool features that you would expect to be in a readline-enabled application. If you are used to searching your Bash history using Ctrl-s, you won’t have a problem transitioning to the same functionality in IPython. Here, we’ve defined a few variables, then searched back through the history:

In [1]: foo = 1

In [2]: bar = 2

In [3]: bam = 3

In [4]: d = dict(foo=foo, bar=bar, bam=bam)

In [5]: dict2 = dict(d=d, foo=foo)

In [6]: <CTRL-s>

(reverse-i-search)`fo': dict2 = dict(d=d, foo=foo)

<CTRL-r>

(reverse-i-search)`fo': d = dict(foo=foo, bar=bar, bam=bam)

We typed Ctrl-r to start the search, then typed in fo as the search criteria. It brought up the line we entered that is denoted by IPython as In [5]. Using readline’s search functionality, we hit Ctrl-r and it matched the line we entered that is denoted by IPython as In [4].

There are many more things you can do with readline, but we’ll touch only briefly on them. Ctrl-a will take you to the beginning of a line and Ctrl-e will take you to the end of a line. Ctrl-f will move forward one character and Ctrl-b will move backward one character. Ctrl-d deletes one character and Ctrl-h deletes one character backward (backspace). Ctrl-p moves one line backward in the history and Ctrl-n moves one line forward in your history. For more readline functionality, enter man readline on your *nix system of choice.

hist command

In addition to providing access to the history functionality of the readline library, IPython also provides its own history function named history or hist for short. With no parameters, hist prints a sequential list of the input commands received from the user. By default, this list will be numbered. In this example, we set a few variables, change the directory, and then run the hist command:

In [1]: foo = 1

In [2]: bar = 2

In [3]: bam = 3

In [4]: cd /tmp
/tmp

In [5]: hist
1: foo = 1
2: bar = 2
3: bam = 3
4: _ip.magic("cd /tmp")
5: _ip.magic("hist ")

Items 4 and 5 in the history above are magic functions. Note that they have been modified by IPython and you can see what is going on under the covers through the IPython magic() function call.

To suppress the line numbers, use the -n option. Here is an example using the -n option for hist:

kIn [6]: hist -n
foo = 1
bar = 2
bam = 3
_ip.magic("cd /tmp")
_ip.magic("hist ")
_ip.magic("hist -n")

It is very helpful if you’ve been working in IPython and want to paste a section of your IPython code into a text editor.

The -t option returns a “translated” view of the history that shows the way IPython sees the commands that have been entered. This is the default. Here is the history we’ve built up so far run through with the -t flag:

In [7]: hist -t
1: foo = 1
2: bar = 2
3: bam = 3
4: _ip.magic("cd /tmp")
5: _ip.magic("hist ")
6: _ip.magic("hist -n")
7: _ip.magic("hist -t")

The “raw history,” or -r, flag will show you exactly what you typed. Here is the result of the earlier example, adding the “raw history” flag:

In [8]: hist -r
1: foo = 1
2: bar = 2
3: bam = 3
4: cd /tmp
5: hist
6: hist -n
7: hist -t
8: hist -r

IPython’s -g flag function also provides a facility to search through your history for a specific pattern. Here is the earlier example with the -g flag used to search for hist:

In [9]: hist -g hist
0187: hist
0188: hist -n
0189: hist -g import
0190: hist -h
0191: hist -t
0192: hist -r
0193: hist -d
0213: hist -g foo
0219: hist -g hist
===
^shadow history ends, fetch by %rep <number> (must start with 0)
=== start of normal history ===
5 : _ip.magic("hist ")
6 : _ip.magic("hist -n")
7 : _ip.magic("hist -t")
8 : _ip.magic("hist -r")
9 : _ip.magic("hist -g hist")

Notice that the term “shadow history” is returned in the previous example. “Shadow history” is a history of every command you have ever entered. Those items are displayed at the beginning of the result set and begin with a zero. History results from this session are stored at the end of the result set and do not start with a zero.

History results

In both Python and IPython, you can access not only your history of the commands you entered, but also access the history of your results. The first way to do this is using the _ flag, which means “the last output.” Here is an example of the way the _ function works in IPython:

In [1]: foo = "foo_string"

In [2]: _

Out[2]: ''

In [3]: foo

Out[3]: 'foo_string'

In [4]: _

Out[4]: 'foo_string'

In [5]: a = _

In [6]: a

Out[6]: 'foo_string'

When we defined foo in In [1], the _ in In [2] returned an empty string. When we output foo in In [3], we were able to use _ to get the result back in In [4]. And in In [5], we were able to save it off to a variable named a.

Here is the same example using the standard Python shell:

>>> foo = "foo_string"
>>> _
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name '_' is not defined
>>> foo
'foo_string'
>>> _
'foo_string'
>>> a = _
>>> a
'foo_string'

We see pretty much the same thing in the standard Python shell that we see in IPython, except that trying to access _ before anything has been output results in a NameError exception.

IPython takes this “last output” concept a step further. In the description of the Shell Execute” function, we described the ! and !! operators and explained that you can’t store the results of !! in a variable but can use it later. In a nutshell, you can access any result that was output using the syntax underscore (_) followed by a number_[0-9]* syntax. The number must correspond to the Out [0-9]* result that you want to see.

To demonstrate this, we’ll first list files but not do anything with the output:

In [1]: !!ls apa*py

Out[1]: SList (.p, .n, .l, .s, .grep(), .fields() available). Value:
0: apache_conf_docroot_replace.py
1: apache_log_parser_regex.py
2: apache_log_parser_split.py

In [2]: !!ls e*py

Out[2]: SList (.p, .n, .l, .s, .grep(), .fields() available). Value:
0: elementtree_system_profile.py
1: elementtree_tomcat_users.py

In [3]: !!ls t*py

Out[3]: SList (.p, .n, .l, .s, .grep(), .fields() available). Value:
0: test_apache_log_parser_regex.py
1: test_apache_log_parser_split.py

We should have access to Out [1-3] by using _1, _2, and _3. So, we’ll attach a more meaningful name to them:

In [4]: apache_list = _1

In [5]: element_tree_list = _2

In [6]: tests = _3

Now, apache_list, element_tree_list, and tests contain the same elements that were output in Out [1], Out [2], and Out [3], respectively:

In [7]: apache_list

Out[7]: SList (.p, .n, .l, .s, .grep(), .fields() available). Value:
0: apache_conf_docroot_replace.py
1: apache_log_parser_regex.py
2: apache_log_parser_split.py

In [8]: element_tree_list

Out[8]: SList (.p, .n, .l, .s, .grep(), .fields() available). Value:
0: elementtree_system_profile.py
1: elementtree_tomcat_users.py

In [9]: tests

Out[9]: SList (.p, .n, .l, .s, .grep(), .fields() available). Value:
0: test_apache_log_parser_regex.py
1: test_apache_log_parser_split.py

But the whole point of all this is that, in IPython, you can access previous output results with either the naked _ special variable, or with an explicit numbered output reference by using _ followed by a number.

Automation and Shortcuts

As if IPython hasn’t done enough to improve your productivity, it also provides a number of functions and features to help you automate your IPython tasks and usage.

alias

We’ll first mention the alias “magic” command. We already covered this earlier in this chapter, so we won’t rehash usage of it again. But we wanted to just point out here that alias cannot only help you use *nix shell commands directly from within IPython, it can help you automate tasks as well.

macro

The macro function lets you define a block of code that can be executed later inline with whatever code you are working on. This is different from creating functions or methods. The macro, in a sense, becomes aware of the current context of your code. If you have a common set of processing steps you frequently execute on all your files, you can create a macro to work on the files. To get a feel for the way a macro will work on a list of files, look at the following example:

In [1]: dirlist = []

In [2]: for f in dirlist:
   ...:     print "working on", f
   ...:     print "done with", f
   ...:     print "moving %s to %s.done" % (f, f)
   ...:     print "*" * 40
   ...:     
   ...:     

In [3]: macro procdir 2
Macro `procdir` created. To execute, type its name (without quotes).
Macro contents:
for f in dirlist:
    print "working on", f
    print "done with", f
    print "moving %s to %s.done" % (f, f)
    print "*" * 40

At the time that we created the loop in In [2], there were no items in dirlist for the loop to walk over, but because we anticipated that future iterations would include items in dirlist, we created a macro named procdir to walk over the list. The syntax for creating a macro is macro macro_name range_of_lines, where the range of lines is a list of the lines from your history that you want incorporated into the macro. The lines for your macro list should be designated by a space-separated list of either numbers or ranges of numbers (such as 1-4).

In this example, we create a list of filenames and store them in dirlist, then execute the macro procdir. The macro will walk over the list of files in dirlist:

In [4]: dirlist = ['a.txt', 'b.txt', 'c.txt']

In [5]: procdir
------> procdir()
working on a.txt
done with a.txt
moving a.txt to a.txt.done
****************************************
working on b.txt
done with b.txt
moving b.txt to b.txt.done
****************************************
working on c.txt
done with c.txt
moving c.txt to c.txt.done
****************************************

Once you have a macro defined, you can edit it. This will open in your defined text editor. This can be very helpful when you are tweaking a macro to make sure it is right before you persist it.

store

You can persist your macros and plain Python variables with the store magic function. The simple standard use of store is store variable. However, store also takes a number of parameters that you may find useful: the -d variable function deletes the specified variable from the persistence store; -z function deletes all stored variables; and the -r function reloads all variables from the persistence store.

reset

The reset function deletes all variables from the interactive namespace. In the following example, we define three variables, use whos to verify they are set, reset the namespace, and use whos again to verify that they are gone:

In [1]: a = 1

In [2]: b = 2

In [3]: c = 3

In [4]: whos
Variable   Type    Data/Info
----------------------------
a          int     1
b          int     2
c          int     3

In [5]: reset
Once deleted, variables cannot be recovered. Proceed (y/[n])?  y

In [6]: whos
Interactive namespace is empty.

run

The run function executes the specified file in IPython. Among other things, this allows you to work on a Python module in an external text editor and interactively test changes you are making in it from within IPython. After executing the specified program, you are returned back to the IPython shell. The syntax for using run is run options specified_file args.

The -n option causes the module’s __name__ variable to be set not to '__main__', but to its own name. This causes the module to be run much as it would be run if it were simply imported.

The -i option runs the module in IPython’s current namespace and, thereby, gives the running module access to all defined variables.

The -e option causes IPython to ignore calls to sys.exit() and SystemExit exceptions. If either of these occur, IPython will just continue.

The -t option causes IPython to print out information about the length of time it took the module to run.

The -d option causes the specified module to be run under the Python debugger (pdb).

The -p option runs the specified module under the Python profiler.

save

The save function will save the specified input lines to the specified output file. Syntax for using save is save options filename lines. The lines may be specified in the same range format as is used for macro. The only save option is -r, which designates that raw input rather than translated should be saved. Translated input, which is standard Python, is the default.

rep

The final automation-enabling function is rep. The rep function takes a number of parameters that you might find useful. Using rep without parameters takes the last result that was processed and places a string representation of it on the next input line. For example:

In [1]: def format_str(s):
   ...:     return "str(%s)" % s
   ...: 

In [2]: format_str(1)

Out[2]: 'str(1)'

In [3]: rep

In [4]: str(1)

The rep call at In [3] causes the text you see to be placed on In [4]. This allows you to programatically generate input for IPython to process. This comes in handy, particularly when you are using a combination of generators and macros.

A fairly common use case for rep without arguments is lazy, mouseless editing. If you have a variable containing some value, you can edit that value directly. As an example, assume that we are using a function that returns to the bin directory for specific installed packages. We’ll store the bin directory in a variable called a:

In [2]: a = some_blackbox_function('squiggly')

In [3]: a

Out[3]: '/opt/local/squiggly/bin'

If we type rep right here, we’ll see /opt/local/squiggly/bin on a new input line with a blinking cursor expecting us to edit it:

In [4]: rep

In [5]: /opt/local/squiggly/bin<blinking cursor>

If we wanted to store the base directory of the package rather than the bin directory, we can just delete the bin from the end of the path, prefix the path with a new variable name, follow that with an equal sign and quotation marks, and suffix it with just a quotation mark:

In [5]: new_a = '/opt/local/squiggly'

Now we have a new variable containing a string that is the base directory for this package.

Sure, we could have just copied and pasted, but that would have been more work. Why should you leave the comfort of your cozy keyboard to reach for the mouse? You can now use new_a as a base directory for anything that you need to do regarding the squiggly package.

When one number is given as an argument to rep, IPython brings up the input from that particular line of history and places it on the next line, and then places the cursor at the end of that line. This is helpful for executing, editing, and re-executing single lines or even small blocks of code. For example:

In [1]: map = (('a', '1'), ('b', '2'), ('c', '3'))

In [2]: for alph, num in map:
   ...:     print alph, num
   ...:     
   ...:     
a 1
b 2
c 3

Here, we edit In [2] and print the number value times 2 rather than a noncomputed value. We could either type the for loop in again, or we can use rep:

In [3]: rep 2

In [4]: for alph, num in map:
    print alph, int(num) * 2
   ...:     
   ...:     
a 2
b 4
c 6

The rep function also takes ranges of numbers for arguments. The numeric range syntax is identical to the macro numeric range syntax that we discussed elsewhere in this chapter. When you specify a range for rep, the lines are executed immediately. Here is an example of rep:

In [1]: i = 1

In [2]: i += 1

In [3]: print i
2

In [4]: rep 2-3
lines [u'i += 1
print i
']
3

In [7]: rep 2-3
lines [u'i += 1
print i
']
4

We defined a counter incrementer and code that prints out the current count in In [1] through In [3]. In In [4] and In [7], we told rep to repeat lines 2 and 3. Notice that 2 lines (5 and 6) are missing since they were executed after In [4].

The last option for rep that we’ll go over is passing in a string. This is more like “passing in a word to rep” or even “passing in a nonquoted search string to rep.” Here is an example:

In [1]: a = 1

In [2]: b = 2

In [3]: c = 3

In [4]: rep a

In [5]: a = 1

We defined a few variables and told rep to repeat the last line that has an “a” in it. It brought In [1] back to us to edit and re-execute.

Summary

IPython is one of the most well-worn tools in our toolbox. Having mastery of a shell is like having mastery of a text editor: the more proficient you are, the more quickly you can cut through the tedious parts of the task you are working on. When we started working with IPython a few years ago, it was an amazingly powerful tool. Since then, it has grown into even more. The grep function and the ability to do string processing are just two of the things that come to mind when we think about the really useful, powerful features that keep emerging from the IPython community. We highly recommend that you dig deeper into IPython. Mastering it is a time investment that you won’t regret.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.143.22.23