Customizing IPython - Magics (8) "IPython in Depth, SciPy2013 Tutorial, Part 3 of 3"¶
На 90-й минуте (третьего) видеоролика речь зашла о настройке пользовательских %magic. Начинвется пост с примера "%timeit A=numpy.random.random((1000,1000))", потом определяются "Define %tic and %toc magics, which can be use for simple timings"... Затем "load a notebook into memory using IPython.nbformat."... После этого можно было оперировать объектом notebook, как dictionary.... Потом "Now I can run all of the code cells with get_ipython().run_cell"... И наконец "write and register an %nbrun line magic to run a notebook"
IPython extends Python by adding shell-like commands called magics.
In [1]:
%lsmagic
Out[1]:
In [2]:
import numpy
In [3]:
%timeit A=numpy.random.random((1000,1000))
In [4]:
%%timeit -n 1
A=numpy.random.random((1000,1000))
b = A.sum()
Defining your own magic¶
As we have seen already, IPython has cell and line magics. You can define your own magics using any Python function and the
register_magic_function
method:
In [1]:
ip = get_ipython()
In [2]:
import time
def sleep_magic(line):
"""A simple function for sleeping"""
t = float(line)
time.sleep(t)
In [3]:
ip.register_magic_function?
In []:
Type: instancemethod
String Form:<bound method ZMQInteractiveShell.register_function of <IPython.kernel.zmq.zmqshell.ZMQInteractiveShell object at 0x0000000007E76A90>>
File: c:\users\kiss\anaconda\lib\site-packages\ipython\core\interactiveshell.py
Definition: ip.register_magic_function(self, func, magic_kind='line', magic_name=None)
Docstring:
Expose a standalone function as magic function for IPython.
This will create an IPython magic (line, cell or both) from a
standalone function. The functions should have the following
signatures:
* For line magics: `def f(line)`
* For cell magics: `def f(line, cell)`
* For a function that does both: `def f(line, cell=None)`
In the latter case, the function will be called with `cell==None` when
invoked as `%f`, and with cell as a string when invoked as `%%f`.
Parameters
----------
func : callable
Function to be registered as a magic.
magic_kind : str
Kind of magic, one of 'line', 'cell' or 'line_cell'
magic_name : optional str
If given, the name the magic will have in the IPython namespace. By
default, the name of the function itself is used.
In [4]:
ip.register_magic_function(sleep_magic, "line", "sleep")
In [5]:
%sleep 2
In [6]:
%sleep?
In []:
Type: Magic function
String Form:<function sleep_magic at 0x00000000080A1518>
Namespace: IPython internal
File: c:\users\kiss\documents\github\ipython-in-depth\notebooks\<ipython-input-2-eaf3ef465508>
Definition: %sleep(line)
Docstring: A simple function for sleeping
Exercise¶
Define
%tic
and %toc
magics, which can be use for simple timings, e.g. wherefor p in range(1,4):
N = 10**p
print "N=%i" % N
%tic
A = np.random.random((N,N))
np.linalg.eigvals(A)
%toc
each %toc
will print the time since the last %tic
. Create separate tic
and toc
functions that read and write a global time variable.
In [7]:
%load soln/tictocf.py
In [8]:
import time
def format_time(dt):
if dt < 1e-6:
return u"%.3g ns" % (dt * 1e9)
elif dt < 1e-3:
return u"%.3g µs" % (dt * 1e6)
elif dt < 1:
return u"%.3g ms" % (dt * 1e3)
else:
return "%.3g s" % dt
def tic(line):
global t0
t0 = time.time()
def toc(line):
global t0
print (format_time(time.time() - t0))
ip = get_ipython()
ip.register_magic_function(tic)
ip.register_magic_function(toc)
In [9]:
import numpy as np
import sys
for p in range(1,4):
N = 10**p
print "N=%i" % N
sys.stdout.flush()
%tic
A = np.random.random((N,N))
np.linalg.eigvals(A)
%toc
Cell Magic¶
Cell magics take two args:
- the line on the same line of the magic
- the cell the multiline body of the cell after the first line
In [10]:
def dummy_cell_magic(line, cell):
"""dummy cell magic for displaying the line and cell it is passed"""
print "line: %r" % line
print "cell: %r" % cell
ip.register_magic_function(dummy_cell_magic, "cell", "dummy")
In [11]:
%%dummy this is the line
this
is the
cell
In [12]:
def parse_magic_line(line):
"""parse a magic line into a name and eval'd expression"""
name, values_s = line.split(None, 1)
values = eval(values_s, get_ipython().user_ns)
return name, values
parse_magic_line("x range(5)")
Out[12]:
Excercise¶
Can you write and register a cell magic that automates the outer iteration, timing a block for various values of a particular variable:
In [13]:
%load soln/scalemagic.py
In [14]:
def scale_magic(line, cell):
"""run a cell block with a variety of input values"""
name, values = parse_magic_line(line)
ns = get_ipython().user_ns
for v in values:
assignment = "%s=%r" % (name, v)
print assignment
ns[name] = v
sys.stdout.flush()
%tic
exec cell in ns
%toc
ip = get_ipython()
ip.register_magic_function(scale_magic, "cell", "scale")
In [15]:
%%scale N [ int(10**p) for p in range(1,4) ]
A = np.random.random((N,N))
np.linalg.eigvals(A)
In [16]:
%%scale N [ int(2**p) for p in np.linspace(6, 11, 11) ]
A = np.random.random((N,N))
np.linalg.eigvals(A)
Executing Notebooks¶
We can load a notebook into memory using
IPython.nbformat
.
In [21]:
import io
import os
from IPython.nbformat import current
In [22]:
def load_notebook(filename):
"""load a notebook object from a filename"""
if not os.path.exists(filename) and not filename.endswith(".ipynb"):
filename = filename + ".ipynb"
with io.open(filename) as f:
return current.read(f, 'json')
In [23]:
nb = load_notebook("Sample")
A notebook is just a dictionary with attribute access for convenience.
In [24]:
nb.keys()
Out[24]:
In [25]:
nb.worksheets[0].keys()
Out[25]:
In [26]:
cells = nb.worksheets[0].cells
cells
Out[26]:
We can see all the cells and their type
In [27]:
for cell in cells:
print
print '----- %s -----' % cell.cell_type
if cell.cell_type == 'code':
print cell.input
else:
print cell.source
Now I can run all of the code cells with
get_ipython().run_cell
In [28]:
for cell in cells:
ip = get_ipython()
if cell.cell_type == 'code':
ip.run_cell(cell.input, silent=True)
And we can now use the function that was defined in that notebook:
In [29]:
nb_info(nb)
Exercise¶
Can you write and register an
%nbrun
line magic to run a notebook?%nbrun Sample
In [30]:
%load soln/nbrun.py
In [32]:
%nbrun Sample
The common way to make your magics reusable is to write an Extension, so let's give that a try.
Посты чуть ниже также могут вас заинтересовать
Комментариев нет:
Отправить комментарий