第六章:定制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代碼的octavemagic和rmagic擴展。尤其是在notebook中,它們非常有用。
就像我們在本節中看到的逐行配置模塊,第三方模塊也能實現它們自己的擴展。最后我們將展示怎樣創建一個新的擴展。
示例——逐行分析
line_profiler和memory_profiler包是一個逐行分析工具,它們提供了代碼中花費時間較長和占用內存較多的確切部分的精確細節。它們提供了可以和IPython收工集成的魔法命令。首先,我們需要安裝這些包,如,使用easy_install、pip或針對Windows用戶的Christoph Gohlke的網頁。Windows平台需要額外安裝pstuil包,同樣該包可以在上面網頁中找到。
要激活這兩個包中實現的魔法命令,我們需要編輯IPython的配置文件把下面的幾行添加進去:
c.TerminalIPythonApp.extensions = [
'line_profiler',
'memory_profiler'
]
接着,lprun、mprun、和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_*_的方法,其中的*表示svg、png、jpeg、html、json、pretty或latex。例如,讓我們來定義個帶有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進行數據相關的交互式編程和計算領域中最為先進的工具。
