第六章:定制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執行個體:執行個體代表目前處于活躍狀态的IPython解釋器。其中有用的方法和屬性包括:用于建立新魔法指令的
InteractiveShell
;用于通路使用者命名空間的
register_magics()
,你可以在IPython中使用代碼補全互動式探索所有的示例屬性。對于這個來說,你需要執行下面的指令來獲得目前的執行個體:
user_ns
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進行資料相關的互動式程式設計和計算領域中最為先進的工具。