定制IPython

对于高级用户,IPython可以进行定制和扩展。在本章结束之后,你将会知道:

  • 怎样创建和使用自定义配置文件
  • 怎样为高级功能进行IPython扩展
  • 怎样在notebook中使用不同的语言
  • 怎样创建自己的扩展
  • 怎样使用丰富的前端
  • 怎样把IPython嵌入到你的Python代码

IPython配置文件

配置文件是针对本地主机用户的,包含了IPython参数设置、使用历史、临时数据和日志文件等等。默认情况下,有一个被称为缺省/默认配置文件(defalut profile)。我们也可以在系统shell中使用下面的命令来创建它:

ipython profile create

我们可以使用ipython profile create name来指定配置文件的名字。

配置文件所在位置

配置文件一般情况下存储在~/.ipython~/.config/ipython路径下,其中~是当前用户的家目录。这个目录一般乘坐IPython 目录,有时也被引用做IPYTHONDIR。我们可以使用用于IPython配置的ipython locate命令找到配置文件所在的确切位置,或使用ipython locate profile defalut来指定配置文件目录,其中defalut是配置文件的名字。配置文件的名字一般存储在IPython配置文件加下的一个名为profile_name的文件夹内。

缺省状态下,IPython会使用默认的配置文件启动。我们可以使用--profile命令行参数在运行IPython时指定不同的配置文件。比如:

ipython --profile=name

IPython配置文件

在每一个配置文件中,都有一个专门的名为ipython_config.py的配置文件。这个Python脚本是一个指定不同选项的占位文本。它包含一个完整的包含大多数可用选项及其完整文档的模板,所以很容易就能修改它。

例如,要在一个配置文件中设置pylab模式以及qt循环集成系统自动开启,下面的几行应该出现在对应的ipython_config.py文件中:

# Enable GUI event loop integration ('qt', 'wx', 'gtk', 'glut',
# 'pyglet','osx').
c.InteractiveShellApp.gui = 'qt'
# Pre-load matplotlib and numpy for interactive use, selecting a
# particular matplotlib backend and loop integration.
c.InteractiveShellApp.pylab = 'qt'
# If true, an 'import *' is done from numpy and pylab, when using # 
pylab
c.InteractiveShellApp.pylab_import_all = True

当IPython启动时自动加载脚本

通过某些Python脚本防止在IPYTHONDIE/startuo/目录下,你就可以设置IPython无论何时启动都自动加载这些脚本。这在你想每次启动IPython的时候都自动加载某些模块或一些脚本的时候非常有用。

IPython扩展

在IPython中,IPython扩展可以实现完全的定制行为。它们可以仅用一个魔方命令手动加载,或当IPython启动时自动加载。

IPython原生包含多种扩展。它们基本上都支持在IPython中运行非Python代码。例如,就像我们在第五章——高性能并行化计算中看到的那样,cythonmagic扩展为可以在IPython中直接编写Cython代码提供了%%cython魔法小格命令。相似的内建扩展包括支持IPython执行Octave和R代码的octavemagicrmagic扩展。尤其是在notebook中,它们非常有用。

就像我们在本节中看到的逐行配置模块,第三方模块也能实现它们自己的扩展。最后我们将展示怎样创建一个新的扩展。

示例——逐行分析

line_profilermemory_profiler包是一个逐行分析工具,它们提供了代码中花费时间较长和占用内存较多的确切部分的精确细节。它们提供了可以和IPython收工集成的魔法命令。首先,我们需要安装这些包,如,使用easy_installpip或针对Windows用户的Christoph Gohlke的网页。Windows平台需要额外安装pstuil包,同样该包可以在上面网页中找到。

要激活这两个包中实现的魔法命令,我们需要编辑IPython的配置文件把下面的几行添加进去:

c.TerminalIPythonApp.extensions = [
'line_profiler',
'memory_profiler'
]

接着,lprunmprun、和memit魔法命令就可以使用了。当配置文件的函数定义在一个文件中而不是交互式会话中时这个逐行分析器能工作的很好,这是因为分析器接着可以显示配置报告中的每一行内容。

作为一个示例,让让我们使用下面的代码创建一个名为myscript.py的脚本:

import numpy as np
import matplotlib.pyplot as plt
def myfun():
    dx = np.random.randn(1000, 10000)
    x = np.sum(dx, axis=0)
    plt.hist(x, bins=np.linspace(-100, 100, 20))

该函数经过10000步模拟了10000个随机行走(布朗运动),并 在模拟过程的最后绘制出了质点位置的直方图。

现在,我们将把这个函数加载到IPython中并对其进行简单的介绍。%lprub魔法命令接受一个Python语句和一个用于逐行介绍的函数列表,且开启了一个-f选项:

In [1]: from myscript import myfun
In [2]: lprun -f myfun myfun()
Timer unit: 5.13284e-07 s
File: myscript.py
Function: myfun at line 3
Total time: 1.26848 s
Line # Hits Time Per Hit % Time Line Contents
==============================================================
3 def myfun():
4 1 1783801 1783801.0 72.2 dx = 
np.random.randn(1000, 1000)
5 1 262352 262352.0 10.6 x = 
np.cumsum(dx, axis=0)
6 1 425142 425142.0 17.2 t = 
np.arange(1000)
7 
np.histogram2d(t, x)

我们可以观察到大部分的执行时间发生在dx数组创建的时候。

%mprun魔法命令可以使用相似的方法进行内存分析。

在分析复杂Python应用的时候这些逐行分析器十分有用。在IPython中通过简单的魔法命令交互式的使用非常方便。

创建新的扩展

要创建一个新的扩展,我们需要在Python路径下创建一个字典形式的Python模块。可以将其放在当前目录或`IPYTHONDIR/extensions/。

这个扩展用来实现一个load_ipython)extension(ipython)函数,采用当前的InteracyiveShell实例作为参数(也可以是当扩展未被加载时会被调用的unload_ipython_extension(ipython)),这个实例可以用来注册新的魔法命令,访问用户命名空间,执行代码,等等。这个加载函数会在扩展被加载后调用,也就是说会发生在%load_ext%reload_ext魔法命令被执行的时候。要实现在IPython启动的时候自动加载一个模块,我们需要将这个模块的名字添加到IPython配置文件中的c.TerminaliPythonApp.extensions列表中。

InteractiveShell实例InteractiveShell实例代表当前处于活跃状态的IPython解释器。其中有用的方法和属性包括:用于创建新魔法命令的register_magics();用于访问用户命名空间的user_ns,你可以在IPython中使用代码补全交互式探索所有的示例属性。对于这个来说,你需要执行下面的命令来获得当前的实例: ip = get_ipython()

示例——在IPython中执行C++代码

在这个实例中,我们将创建一个新的扩展以在IPython中执行C++代码。这只是一个用于示范的示例,在现实项目中,更好的方法是使用Cython或SciPy.weave。

该扩展定义了一个名为cpp的小格魔法命令。思路是可以在小格内直接编写C++代码,且能够被自动的编译和执行。小格输出将会包含代码的标准输出。这里是一个这个扩展是怎样工作的说明:

  • 我们创建一个继承自IPython.core.magic.Magics的新类
  • 在这个类中,我们使用cell_magic装饰器创建一个新的方法:它将用来实现cpp小格魔法
  • 这个方法接受小格内的代码作为输入,将其中的C++代码存储到一个临时文件内,并调用g++编译器来创建一个可执行文件
  • 该方法接着会调用这个先创建的可执行文件并返回其输出
  • load_ipython_extension函数中,我们注册这个魔法类

将下面的代码添加到一个名为cppmagic.py的脚本文件中:

import IPython.core.magic as ipym
@ipym.magics_class
class CppMagics(ipym.Magics):
    @ipym.cell_magic
    def cpp(self, line, cell=None):
        """Compile, execute C++ code, and return the standard 
        output."""
        # Define the source and executable filenames.
        source_filename = 'temp.cpp'
        program_filename = 'temp.exe'
# Write the code contained in the cell to the C++ file.
        with open(source_filename, 'w') as f:
            f.write(cell)
# Compile the C++ code into an executable.
        compile = self.shell.getoutput("g++ {0:s} -o {1:s}".format(
        source_filename, program_filename))
# Execute the executable and return the output.
        output = self.shell.getoutput(program_filename)
        return output
    def load_ipython_extension(ipython):
        ipython.register_magics(CppMagics)

下面的截图展示了怎样在IPython notebook中方便地使用这个扩展来编写C++代码:

【图】

这个代码在Windows上运行正常,且能很容易地是培育Unix系统。

改进这个示例:有多种办法可以改进这个示例:临时文件可以具有唯一的名称且存储在指定的临时目录。编译错误可以很好的处理并重定向到IPython等等。感兴趣的读者可以看一下IPython/extensions/目录下的内建Cython、Octave、R魔法扩展中与示例相似的一部分。跟普遍的来说,相同的技术可以被用来在IPython中运行。设置可以在Python和其他语言之间共享变量。

IPython扩展在notebook环境中非常强大,因为他们可以让cell代码实现任意复杂的行为。

扩展索引一个有IPython 用户创建的IPython扩展索引可以在下面找到: https://github.com/ipython/ipython/wiki/Extensions-Index。如果你已经创建了你自己的扩展,别犹豫把它添加到这里吧。

前端中的丰富展示

notebook和Qt控制台能显示更为丰富的对象展示。都能显示位图和SVG图片,且notebook还支持视频,HTML代码和LaTex数学方程式。可以使用下面的这些类非常容易地显示丰富的对象:只需要实现一个名为_repr_*_的方法,其中的*表示svgpngjpeghtmljsonprettylatex。例如,让我们来定义个带有SVG显示方法的DIsc类:


In [1]: class Disc(object):
            def __init__(self, size, color= ared'):
                self.size = size
                self.color = color
            def _repr_svg_(self):
                return """<svg xmlns="http://    www.w3.org/2000/svg" 
                    version="1.1">
                    <circle cx="{0:d}" cy="{0:d}" r="{0:d}" 
                    fill="{1:s}" />
                    </svg>""".format(self.size, self.color)

这个类的构造函数接受一个以像素为单位的半径大小值和一个表示颜色的字符串。接着,当这个类的示例指向标准输出时,SVG图像就会像下面截图这样出现在显示在小格内: 【图】

另外一种显对象富文本的方法是使用IPython.diaplay模块。你可以交互式地获得Tab补全提示的所有被支持的表现。例如,下面的截图展示了怎样在notebook中渲染LaTex方程式:

【图】 notebook的丰富表现功能使得他非常适合创建教学内容、展示、博客、书籍等。同事notebook文件可以以导出为HTML或PDF文件。

IPython的后续版本可能会支持定制的JS扩展和部件来提供更为丰富的交互式展示。

嵌入IPython

可以从任意的Python脚本中启动IPython,甚至当标准的Python解释器运行这个脚本。在当你某时需要和一个复杂的Python程序进行交互的时候、不想或不能使用IPython解释器进行整个程序的构建时候这一特性非常有用。例如,在一个科学计算环境中,你也许想要在某些自动运行某些计算加强算法重启这些程序之前暂停一下来查看一下数据,绘制一些图像等等。另外一个可能用到地方是方便用户从IPython命令行接口和GUI中的部件进行交互的集成。

在一个程序中集成IPython的最简单办法是在在你的Python程序的任意地方调用IPython.embed()(当然需要先import IPython)。你还可以指定定制选项,比如命令行接口的输入输出模板,启动退出消息等等。你可以在下面的网站找到更多相关的信息: http://ipython. org/ipython-doc/stable/interactive/reference.html#embedding-ipython。

结束语

此时此刻,你应该已经被IPyton的强大和灵活性说服了。IPython不仅原生提供了大量让人激动的有用功能,而且还允许你在任意层面对它进行扩展和定制。而且有一点你要清楚,这个项目还在发展。尽管它创建于10年之前,但截至本书写作的时候他的1.0版本仍未发布。IPython的和兴功能现在已经相当成熟和稳定。notebook是最近刚开发出的功能,预计将会在未来的几年重点发展。在notebook中创建定制的交互式部件可能已经提上了计划日程,也许会成为整个项目的主要功能。更多有关最近开发进展的信息可以在下面的网页上找到:https://github.com/ipython/ipython/wiki/Roadmap:-IPythonand http://ipython.org/_static/sloangrant/sloan-grant.html。

最后,IPython是一个活跃的开源项目,这意味着它欢迎任何人为其做贡献。贡献可以只是一个报告或解决一个bug,但这也常常是有用的并被高度感激和尊敬的!与此相关,欢迎任何人在遵守一般社区礼仪的情况下寻求帮助。开发者和大多数活跃的用户会很乐意提供帮助。下面是一些有用的链接:

  • GitHub 项目主页:
  • WiKi(维基主页):
  • 用户邮件列表
  • 聊天室:

总结

在这一章中我们讲述了怎样通过extensions的方式来定制和扩展IPython。我们看到非Python语言也能从IPython中方便地调用。尤其是在notebook环境中,任意的代码都能在小格内进行粘贴复制、显式编译、于当前Python命名空间进行评估测试。notebook还支持丰富的前端显示,不久的将来,交互式部件的出现将会使它成为使用Python进行数据相关的交互式编程和计算领域中最为先进的工具。