IPython Notebook简介1

IPython Notebook简介1

IPython notebook目前已经成为用Python做教学、计算、科研的一个重要工具。本文介绍IPython notebook的一些基本用法,以及如何使用它调试Cython程序。

IPython Notebook使用浏览器作为界面,向后台的IPython服务器发送请求,并显示结果。在浏览器的界面中使用单元(Cell)保存各种信息。Cell有多种类型,经常使用的有表示格式化文本的Markdown单元,和表示代码的Code单元。

每个代码单元都有一个输出区域,在Code单元中输入代码,按 Shift-Enter 将运行此代码,代码中最后一个表达式的值将输出区域显示。如果希望屏蔽输出,可以在最后一条语句之后添加一个分号:”;”。此外,代码中还可以使用print语句在输出区域中显示信息。

在Markdown单元中还可以直接使用Html和Javascript。

数学公式

在Markdown单元中可以使用LaTeX表示数学公式,例如

。数学公式的显示使用MathJax,缺省情况下,MathJax从网络上下载,如果希望离线使用它,需要在IPython Notebook中输入如下代码,把MathJax安装到本地磁盘中:

fromIPython.external.mathjaximportinstall_mathjaxinstall_mathjax()

Code单元的输出也可以显示为数学公式,例如在单元中输入如下代码,将显示为数学公式:

fromIPython.displayimportLatexLatex(r"$\sqrt{x^2+y^2}$")

SymPy的表达式也可以显示为LaTex,例如:

%load_extsympyprintingfromsympyimport*x,y=symbols("x,y")sqrt(x**2+y**2)

以%开头的为IPython的命令(Magic Command),这里通过%load_ext命令载入sympyprinting扩展插件,载入此插件之后,所有的SymPy表达式都显示为数学公式。

各种显示

IPython.display模块中提供了许多显示Python返回值的类,例如下面的代码用Image类显示”python.png”图片,缺省路径为Notebook文件所在的目录:

fromIPython.displayimportImageImage(filename="python.png")

Image还可以用来显示表示图像的字符串。例如下面的代码通过cv2的imencode()将NumPy数组转换为一个表示PNG图像数据的数组,然后将此数组转换为字符串之后通过Image()将显示为图像:

importcv2importnumpyasnpfromIPython.displayimportImageimg=np.random.randint(0,255,(250,250,3))cv2.blur(img,(11,11),img)r,dat=cv2.imencode(".png",img)Image(dat.tostring())

此外,还可以通过HTML和Javascript将Python代码的输出显示为Html,或者作为Javascript运行。

fromIPython.displayimportJavascriptJavascript("alert('ok')")

将在浏览器中运行Javascript代码。

Magic命令

IPython中Magic命令有两种执行方式,以%开始的命令被称为行命令,它只对单行有效,以%%开头的为单元命令,它放在单元的第一行,对整个单元有效。例如timeit命令可以快速测试代码的执行效率,它可以作为行命令或者单元命令。

%timeit1+1%timeit1.0+1.0%timeit"1"+"1"

10000000 loops, best of 3: 52 ns per loop

10000000 loops, best of 3: 53.4 ns per loop

10000000 loops, best of 3: 50.9 ns per loop

%%timeits=0foriinxrange(100):s+=i

100000 loops, best of 3: 11 us per loop

每个Magic命令都可以指定参数,可以输入timeit?查看其帮助文档。下面让我们看看一些常用的Magic命令。

%pylab命令将载入numpy和pylab,并且将这两个模块中的名字载入到全局名字空间中。缺省参数时,它使用matplotlib的缺省界面库显示图表,如果带inline参数则将图表作为图像插入到Notebook中。使用界面库显示图像时可以使用交互工具,而将图表直接插入到Notebook中则有利于编写文档。

下面的例子,plot和random是从pylab和numpy中载入的。

%pylabinlineplot(random.randn(100));

Welcome to pylab, a matplotlib-based Python environment [backend: module://IPython.zmq.pylab.backend_inline].

For more information, type 'help(pylab)'.

%load可以从文件或者网址载入代码到一个新的单元中,例如下面载入某个matplotlib的示例程序,并执行:

%loadhttp://matplotlib.org/mpl_examples/pylab_examples/histogram_demo.py

#!/usr/bin/env pythonimportnumpyasnpimportmatplotlib.mlabasmlabimportmatplotlib.pyplotaspltmu,sigma=100,15x=mu+sigma*np.random.randn(10000)# the histogram of the datan,bins,patches=plt.hist(x,50,normed=1,facecolor='green',alpha=0.75)# add a 'best fit' liney=mlab.normpdf(bins,mu,sigma)l=plt.plot(bins,y,'r--',linewidth=1)plt.xlabel('Smarts')plt.ylabel('Probability')plt.title(r'$\mathrm{Histogram\ of\ IQ:}\ \mu=100,\ \sigma=15$')plt.axis([40,160,0,0.03])plt.grid(True)plt.show()

%prun用于代码的执行性能分析,可以作为行命令和单元命令使用。下面的程序分析numpy.linalg.det()的性能:

%%prunforiinxrange(100):linalg.det(random.rand(10,10))

其输出如下:

3402 function calls in 0.096 seconds

Ordered by: internal time

ncalls  tottime  percall  cumtime  percall filename:lineno(function)

100    0.032    0.000    0.091    0.001 linalg.py:1560(slogdet)

300    0.022    0.000    0.022    0.000 {method 'reduce' of 'numpy.ufunc' objects}

200    0.011    0.000    0.012    0.000 numeric.py:167(asarray)

100    0.006    0.000    0.006    0.000 linalg.py:84(_realType)

100    0.005    0.000    0.005    0.000 linalg.py:151(_assertRank2)

...

%load_ext载入IPython的扩展模块,通过它可以载入更多的Magic命令。下面我们载入cythonmagic模块,并使用%%cython命令编译一个高效的频率统计函数count()。

%load_extcythonmagic

测试Cython代码

Cython的代码基本和Python的代码类似,但是可以使用类型声明,Cython可以使用这些类型声明产生更高效的C语言代码,并编译成Python的扩展模块。使用%%cython命令简化了编译扩展模块的过程,它会自动创建C语言程序,编译并载入。由于扩展模块无法卸载,因此IPython采用的策略是每次编译不同的代码都会产生一个全新的扩展模块。方便我们不退出Python环境即可运行新的代码。

%%cythondefcount(listdata):cdef:dictresult={}inti,length=len(data)objectitemforiinrange(length):item=data[i]ifiteminresult:(result[item]).append(i)else:result[item]=[i]returnresult

下面是count()的Python版本。

fromcollectionsimportdefaultdictdefcountpy(data):result=defaultdict(list)fori,iteminenumerate(data):result[item].append(i)returnresult

先测试二者的结果是否相同:

importrandomdata=[random.randint(0,100)for_inxrange(10000)]count(data)==countpy(data)

True

然后测试它们的执行速度,可以看出Cython版本比Python的要快2倍多。在这个测试中,Cython程序也同样使用列表和字典等对象,但是由于可以直接调用Python的C API,因此Cython版本的效率能提高几倍。如果只是单纯的数值运算,Cython能将程序提升到与C语言相近的速度。

%timeitcountpy(data)%timeitcount(data)

100 loops, best of 3: 4.52 ms per loop

1000 loops, best of 3: 1.8 ms per loop

推荐阅读更多精彩内容