Jupyter Notebook的Magic操做

魔法(Magic)命令

IPython提供了許多魔法命令,使得在IPython環境中的操做更加駕輕就熟。魔法命令都以%或者%%開頭,以%開頭的成爲行命令,%%開頭的稱爲單元命令。行命令只對命令所在的行有效,而單元命令則必須出如今單元的第一行,對整個單元的代碼進行處理。python

執行%magic能夠查看關於各個命令的說明,而在命令以後添加?能夠查看該命令的詳細說明。數組

顯示matplotlib圖表

matplotlib是最著名的Python圖表繪製擴展庫,它支持輸出多種格式的圖形圖像,而且可使用多種GUI界面庫交互式地顯示圖表。使用%matplotlib命令能夠將matplotlib的圖表直接嵌入到Notebook之中,或者使用指定的界面庫顯示圖表,它有一個參數指定matplotlib圖表的顯示方式。app

在下面的例子中,inline表示將圖表嵌入到Notebook中。所以最後一行pl.plot()所建立的圖表將直接顯示在該單元之下,因爲咱們不須要查看最後一行返回的對象,所以以分號結束該行。dom

%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。python2.7

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

內嵌圖表很適合製做圖文並茂的Notebook,然而它們是靜態的沒法進行交互。這時能夠將圖表輸出模式修改成使用GUI界面庫,下面的qt4表示使用QT4界面庫顯示圖表。請讀者根據本身系統的配置,選擇合適的界面庫:’gtk’, ‘osx’, ‘qt’, qt4’, ‘tk’, ‘wx’。svg

執行下面的語句將彈出一個窗口顯示圖表,能夠經過鼠標和鍵盤與此圖表交互。請注意該功能只能在運行IPython Kernel的機器上顯示圖表。函數

%matplotlib qt4
pl.plot(data);

性能分析

性能分析對編寫處理大量數據的程序很是重要,特別是Python這樣的動態語言,一條語句可能會執行不少內容,有的是動態的,有的調用二進制擴展庫,不進行性能分析,就沒法對程序進行優化。IPython提供了許多進行性能分析的魔法命令。oop

%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");

%%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()

%%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?
相關文章
相關標籤/搜索