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:
-nprevents the__name__variable from being set to"__main__"for the Python source file. This prevents the execution of any code in anif __name__ == "__main__":block.
-iruns 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.-pruns 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.
|
Related Reading Learning Python |
Jeremy Jones is a software engineer who works for Predictix. His weapon of choice is Python.
Return to the Python DevCenter.
