Jupyter Notebook的Magic操作

魔法(Magic)命令

IPython提供了许多魔法命令,使得在IPython环境中的操作更加得心应手。魔法命令都以%或者%%开头,以%开头的成为行命令,%%开头的称为单元命令。行命令只对命令所在的行有效,而单元命令则必须出现在单元的第一行,对整个单元的代码进行处理。

执行%magic可以查看关于各个命令的说明,而在命令之后添加?可以查看该命令的详细说明。

显示matplotlib图表

matplotlib是最著名的Python图表绘制扩展库,它支持输出多种格式的图形图像,并且可以使用多种GUI界面库交互式地显示图表。使用%matplotlib命令可以将matplotlib的图表直接嵌入到Notebook之中,或者使用指定的界面库显示图表,它有一个参数指定matplotlib图表的显示方式。

在下面的例子中,inline表示将图表嵌入到Notebook中。因此最后一行pl.plot()所创建的图表将直接显示在该单元之下,由于我们不需要查看最后一行返回的对象,因此以分号结束该行。

%matplotlib inline
import pylab as pl
pl.seed(1)
data = pl.randn(100)
pl.plot(data);

/tech/static/books/scipynew/_images//ipython-200-notebook-magic_output_4_0.png

内嵌图表的输出格式缺省为PNG,可以通过%config命令修改这个配置。%config命令可以配置IPython中的各个可配置对象,其中InlineBackend对象为matplotlib输出内嵌图表时所使用的对象,我们配置它的figure_format="svg",这样将内嵌图表的输出格式修改为SVG。

%config InlineBackend.figure_format="svg"
%matplotlib inline
pl.plot(data);

06161243_Sqys.svg

内嵌图表很适合制作图文并茂的Notebook,然而它们是静态的无法进行交互。这时可以将图表输出模式修改为使用GUI界面库,下面的qt4表示使用QT4界面库显示图表。请读者根据自己系统的配置,选择合适的界面库:’gtk’, ‘osx’, ‘qt’, qt4’, ‘tk’, ‘wx’。

执行下面的语句将弹出一个窗口显示图表,可以通过鼠标和键盘与此图表交互。请注意该功能只能在运行IPython Kernel的机器上显示图表。

%matplotlib qt4
pl.plot(data);

性能分析

性能分析对编写处理大量数据的程序非常重要,特别是Python这样的动态语言,一条语句可能会执行很多内容,有的是动态的,有的调用二进制扩展库,不进行性能分析,就无法对程序进行优化。IPython提供了许多进行性能分析的魔法命令。

%timeit调用timeit模块对单行语句重复执行多次,计算出其执行时间。下面的代码测试修改列表单个元素所需的时间。

a = [1,2,3]
%timeit a[1] = 10
10000000 loops, best of 3: 164 ns per loop

%%timeit则用于测试整个单元中代码的执行时间。下面的代码测试空列表中循环添加10个元素所许的时间:

%%timeit
a = []
for i in xrange(10):
    a.append(i)
100000 loops, best of 3: 3.85 µs per loop

timeit命令会重复执行代码多次,而time则只执行一次代码,输出代码的执行情况,和timeit命令一样,它可以作为行命令和单元命令。下面的代码统计往空列表中添加10万个元素所需的时间。

%%time
a = []
for i in xrange(100000):
    a.append(i)
CPU times: user 44 ms, sys: 4 ms, total: 48 ms
Wall time: 51.9 ms

time和timeit命令都将信息使用print输出,如果希望用程序分析这些信息,可以使用%%capture命令,将单元格的输出保存为一个对象。下面的程序对不同长度的数组调用sort()函数进行排序,并使用%timeit命令统计排序所需的时间。为了加快程序的计算速度,这里通过-n20指定代码的运行次数为20次。由于使用了%%capture命令,程序执行之后没有输出,所有输出都被保存进了result对象。

%%capture result
import numpy as np
for n in [1000, 5000, 10000, 50000, 100000, 500000]:
    arr = np.random.rand(n)
    print "n={0}".format(n)
    %timeit -n20 np.sort(arr)

result.stdout属性中保存通过标准输出管道中的输出信息:

print result.stdout
n=1000
20 loops, best of 3: 127 us per loop
n=5000
20 loops, best of 3: 746 us per loop
n=10000
20 loops, best of 3: 1.69 ms per loop
n=50000
20 loops, best of 3: 9.22 ms per loop
n=100000
20 loops, best of 3: 19.7 ms per loop
n=500000
20 loops, best of 3: 110 ms per loop

下面的代码使用re模块从上面的字符串中获取数组长度和排序执行时间的信息,并将其绘制成图表。图表的横坐标为对数坐标轴,表示数组的长度;纵坐标为平均每个元素所需的排序时间。可以看出每个元素所需的平均排序时间与数组的长度的对数成正比,因此可以计算出排序函数sort()的时间复杂度为:O(n \log{n})

def tosec(t):
    units = {"ns":1e-9, "us":1e-6, "ms":1e-3, "s":1}
    value, unit = t.strip().split()
    return float(value) * units[unit]

import re
info = re.findall(r"n=(.+?)\n.+?best of 3: (.+?) per loop", result.stdout)
info = [(int(t0), tosec(t1)) for t0, t1 in info]
x, y = np.r_[info].T
pl.semilogx(x, y/x, "-o");

06161243_2aKg.svg

%%prun命令调用profile模块,对单元中的代码进行性能剖析。下面的性能剖析显示fib()运行了21891次,而fib_fast()则只运行了20次。

%%nopage
%%prun
def fib(n):
    if n < 2:
        return 1
    else:
        return fib(n-1) + fib(n-2)

def fib_fast(n, a=1, b=1):
    if n == 1:
        return b
    else:
        return fib_fast(n-1, b, a+b)

fib(20)
fib_fast(20)
21913 function calls (4 primitive calls) in 0.084 seconds

 Ordered by: internal time

 ncalls  tottime  percall  cumtime  percall filename:lineno(function)
21891/1    0.084    0.000    0.084    0.084 <string>:2(fib)
   20/1    0.000    0.000    0.000    0.000 <string>:8(fib_fast)
      1    0.000    0.000    0.084    0.084 <string>:2(<module>)
      1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

代码调试

%debug命令用于调试代码,它有两种用法。一种是在执行代码之前设置断点进行调试,第二种则是在代码抛出异常之后,执行%debug命令查看调用堆栈。下面先演示第二种方法的用法:

import pylab as pl
import numpy as np

def test_debug():
    x = np.linspace(1, 50, 10000)
    img = np.sin(x*np.cos(x))
    pl.imshow(img)
    pl.show()

test_debug()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-8-718b55b6e471> in <module>()
      8     pl.show()
      9
---> 10 test_debug()

<ipython-input-8-718b55b6e471> in test_debug()
      5     x = np.linspace(1, 50, 10000)
      6     img = np.sin(x*np.cos(x))
----> 7     pl.imshow(img)
      8     pl.show()
      9

/home/hyry/anaconda/lib/python2.7/site-packages/matplotlib/pyplot.pyc in imshow(X, cmap, norm, aspect, interpolation, alpha, vmin, vmax, origin, extent, shape, filternorm, filterrad, imlim, resample, url, hold, **kwargs)
   2735                         vmax=vmax, origin=origin, extent=extent, shape=shape,
   2736                         filternorm=filternorm, filterrad=filterrad,
-> 2737                         imlim=imlim, resample=resample, url=url, **kwargs)
   2738         draw_if_interactive()
   2739     finally:

/home/hyry/anaconda/lib/python2.7/site-packages/matplotlib/axes.pyc in imshow(self, X, cmap, norm, aspect, interpolation, alpha, vmin, vmax, origin, extent, shape, filternorm, filterrad, imlim, resample, url, **kwargs)
   7103                        filterrad=filterrad, resample=resample, **kwargs)
   7104
-> 7105         im.set_data(X)
   7106         im.set_alpha(alpha)
   7107         self._set_artist_props(im)

/home/hyry/anaconda/lib/python2.7/site-packages/matplotlib/image.pyc in set_data(self, A)
    420         if (self._A.ndim not in (2, 3) or
    421             (self._A.ndim == 3 and self._A.shape[-1] not in (3, 4))):
--> 422             raise TypeError("Invalid dimensions for image data")
    423
    424         self._imcache =None

TypeError: Invalid dimensions for image data
%debug
>  [1;32m/home/hyry/anaconda/lib/python2.7/site-packages/matplotlib/image.py [0m(422) [0;36mset_data [1;34m() [0m
 [1;32m    421  [1;33m            (self._A.ndim == 3 and self._A.shape[-1] not in (3, 4))):
 [0m [1;32m--> 422  [1;33m             [1;32mraise [0m  [0mTypeError [0m [1;33m( [0m [1;34m"Invalid dimensions for image data" [0m [1;33m) [0m [1;33m [0m [0m
 [0m [1;32m    423  [1;33m [1;33m [0m [0m
 [0m
ipdb> l
%config InlineBackend.figure_format="svg"
%matplotlib inline

def test_debug():
    x = np.linspace(1, 50, 10000)
    img = np.sin(x*np.cos(x)).reshape(100, -1)
    pl.imshow(img)
    pl.show()

test_debug()

06161243_lAQR.svg

%%writefile debug_test.py
a = 1
b = 2
print a + b
Writing debug_test.py
%debug --breakpoint debug_test.py:2
Breakpoint 1 at /home/hyry/Dropbox/scipybook2/debug_test.py:2
NOTE: Enter 'c' at the ipdb>  prompt to continue execution.
%run -d debug_test.py
Breakpoint 1 at /home/hyry/Dropbox/scipybook2/debug_test.py:1
NOTE: Enter 'c' at the ipdb>  prompt to continue execution.
>  [1;32m/home/hyry/Dropbox/scipybook2/debug_test.py [0m(1) [0;36m<module> [1;34m() [0m
 [1;31m1 [1;32m---> 1  [1;33m [0ma [0m  [1;33m= [0m  [1;36m1 [0m [1;33m [0m [0m
 [0m [1;32m      2  [1;33m [0mb [0m  [1;33m= [0m  [1;36m2 [0m [1;33m [0m [0m
 [0m [1;32m      3  [1;33m [1;32mprint [0m  [0ma [0m  [1;33m+ [0m  [0mb [0m [1;33m [0m [0m
 [0m
ipdb> c
%run?

转载于:https://my.oschina.net/u/2306127/blog/832510

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值