Python DevCenter
oreilly.comSafari Books Online.Conferences.

advertisement


Enhanced Interactive Python with IPython
Pages: 1, 2

History

After interactively entering commands, statements, and so on into the IPython shell like this:

In [1]: a = 1

In [2]: b = 2

In [3]: c = 3

In [4]: d = {}

In [5]: e = []

In [6]: for i in range(20):
   ...:     e.append(i)
   ...:     d[i] = b
   ...:

you can quickly view everything you typed like this:

In [7]: hist
1: a = 1
2: b = 2
3: c = 3
4: d = {}
5: e = []
6:
for i in range(20):
    e.append(i)
    d[i] = b

To view the history without the input numbers (here, 1 through 6), use hist -n:

In [8]: hist -n
a = 1
b = 2
c = 3
d = {}
e = []
for i in range(20):
    e.append(i)
    d[i] = b

Using hist -n makes it easier to paste commands into a text editor. To search the history, type a pattern to search for and press Ctrl-P. When something matches, a subsequent Ctrl-P will search backward in your history, and Ctrl-N will search forward.

Edit

When testing an idea at a Python prompt, it is sometimes helpful to edit (and, more importantly, to reedit) some lines of source code with a text editor. Type edit from an IPython prompt to bring up the editor defined by the $EDITOR environment variable, or vi on Unix and Notepad on Windows if you don't have $EDITOR defined. To return to the IPython prompt, exit the editor. Saving and exiting will execute, in the current namespace, the code entered into the editor. If you do not want IPython to execute the code automatically, use edit -x. To reedit the last code that you edited, type edit -p. In the previous feature, I mentioned hist -n making it easier to paste code into an editor. An even easier way of putting code into an editor is using edit with Python list slice syntax. Suppose hist yields:

In [29]: hist
1 : a = 1
2 : b = 2
3 : c = 3
4 : d = {}
5 : e = []
6 :
for i in range(20):
    e.append(i)
    d[i] = b

7 : %hist

To export lines 4, 5, and 6 into an editor, type:

edit 4:7

Debugger Access

Another feature within IPython is its access to the Python debugger. Type the pdb magic word from the IPython shell to toggle automatic debugging upon hitting an exception. With automatic pdb calling enabled, the Python debugger will start automatically when Python encounters an unhandled exception; the current line in the debugger will be the line of code on which the exception occurred. The IPython author states that sometimes when he wants to debug something at a certain line of code, he will put 1/0 at the point he wants to begin debugging, enable pdb, and run the code in IPython. When the interpreter hits the 1/0 line of code, it raises a ZeroDivisionError exception and drops him into a debugging session at that particular line.

Run

Sometimes, when in an interactive shell, it is helpful to execute the contents of a Python source file. Issuing the run magic command followed by a Python source file will run the file in the IPython interpreter (for example, run <run options> <python source file> <options>). The following run options are available:

  • -n prevents the __name__ variable from being set to "__main__" for the Python source file. This prevents the execution of any code in an

    if __name__ == "__main__":

    block.

  • -i runs the file in the current IPython namespace rather than a new one. This is helpful if you want the Python source file to have access to variables defined in the interactive session.

  • -p runs and profiles the file using the Python profiler module. This option does not bring the executed code into the current namespace.

Macros

Macros allow a user to associate a name with a section of Python code so the code can be run later by referring to the name. As with the edit magic word, the list slice notation also works with macro definitions. For example, for a history such as:

In [3]: hist
1: l = []
2:
for i in l:
    print i

you can define a macro with:

In [4]: macro print_l 2
Macro `print_l` created. To execute, type its name (without quotes).
Macro contents:
for i in l:
    print i

Execute it via:

In [5]: print_l
Out[5]: Executing Macro... 

In this case, the list l was empty, so it did not print anything. However, and here is a powerful feature of macros, binding the list l to something and then executing the macro again produces a different result:

In [6]: l = range(5)

In [7]: print_l
Out[7]: Executing Macro...
0
1
2
3
4

It is as if you retyped and executed the code contained in the macro print_l when calling the macro again. It had access to the new binding of the variable l. While macros are absent from Python syntax (and probably always will be), it is certainly a useful feature in an interactive shell.

Profiles

As mentioned earlier, IPython installs multiple configuration files for several different profiles. The configuration files have a naming convention of ipythonrc-<profile name>. In order to start IPython with a specific profile, execute IPython with:

ipython -p <profile name>

One method of creating your own profile is to create an IPython configuration file in the $HOME/.ipython directory named ipythonrc_<your profile> where <your profile> is the name with which you will refer to your profile. This can be useful if you have several projects you work on and each project requires the use of specific, different libraries. You can create a profile for each project and import the modules you frequently use for that project in the configuration file for each project.

System Shell Access

In the default IPython profile, the Unix shell commands (on Unix, of course) cd, pwd, and ls all work like they do from a bash shell. To execute any other shell commands, prepend a ! or !! to them. Use the %sc and %sx magic words to capture the output from shell commands.

The pysh profile is intended as a shell replacement. Starting IPython with a -p pysh flag will cause IPython to accept and execute any commands in the user's $PATH, while at the same time allowing access to all Python modules as well as all Python keywords and built-in functions. For example, to create 500 directories named d_0_d through d_500_d, start IPython with a -p pysh and do something like this:

jjones@cerberus[foo]|2> for i in range(500):
                    |.>     mkdir d_${i}_d
                    |.> 

This will create 500 directories:

jjones@cerberus[foo]|8> ls -d d* | wc -l
500

Notice the mix of the Python range function and the Unix mkdir command.

Note, however, that while ipython -p pysh can provide a powerful shell replacement, it lacks proper job control. Pressing Ctrl-Z while performing some long-running task will stop the IPython session rather than the running subprocess.

Gotchas

While the Python replacement shell is excellent overall, two things provided a small amount of trouble for me. To the credit of the IPython developers, both items are configurable with clear documentation.

The first item was the coloring. On one of my systems, I use xterms with a white background. When requesting information from an object or module with the ? and ?? operators, the object definition line appeared, but it looked like the arguments were missing. That was because the arguments in the constructor displayed in white by default. I resolved this by entering colors LightBG at the IPython shell.

The second item was the combination of autoindent and pasting code. With autoindent enabled, IPython double-indented a section of code I pasted that already had indentation. For example, the following code:

for i in range(10):
    for j in range(10):
        for k in range(10):
            pass

became:

for i in range(10):
        for j in range(10):
                    for k in range(10):
                                    pass

which really was not a problem in this case, because the indentation was consistent among itself. In other circumstances (examples of which elude me just now), it may present a real problem. Invoking the autoindent magic word toggles autoindent so it will not add extra indents--similar to set paste in vim.

Conclusion

IPython is not revolutionary, nor is it entirely novel. Tab completion, searchable history, profiles, and config files have existed in other shells for years, and Python has had levels of introspection for quite some time now. However, IPython has unified some of the most powerful features of mature Unix shells, the Python standard shell, and the Python language into one utility. The result is an unbelievably powerful performance-enhancing tool that I will likely use for years to come. To paraphrase Archimedes, give me a powerful and flexible text editor (vim), interactive shell (IPython), and language (Python), and I can move the world.

Learning Python

Related Reading

Learning Python
By Mark Lutz, David Ascher

Jeremy Jones is a software engineer who works for Predictix. His weapon of choice is Python.


Return to the Python DevCenter.



Sponsored by: