作者:京東科技隱私計算產品部 孫曉軍
1. Jupyter Notebook介紹
圖1 Jupter專案整體架構
[https://docs.jupyter.org/en/latest/projects/architecture/content-architecture.html]
Jupyter Notebook是一套基于web的互動式開發環境,用戶可以在線開發和分享包含代碼和輸出的互動式檔案,支持實時代碼,數學方程,可視化和 markdown等,用途包括:資料清理和轉換,數值模擬,統計建模,機器學習等等,
Jupyter Notebook內部通過內核維護狀態并運行代碼片段,瀏覽器顯示代碼片段和其執行的結果,Jupyter Notebook提供了一個用戶互動式的開發環境,用戶可以通過執行一部分代碼片段,并觀察執行結果,這種互動式設計,使得Jupyter Notebook非常適合資料科學和機器學習的開發作業,
注意本文的代碼和腳本,均基于Jupyter Notebook v6.5.2穩定版本,
2. Jupyter的作業方式
圖2 Jupter Notebook作業方式
[https://docs.jupyter.org/en/latest/projects/architecture/content-architecture.html]
Jupyter的主要作業單元是Jupyter Server和Kernel,其中Jupyter Server用來提供基于Web的界面和API服務,Kernel用來執行代碼片段,瀏覽器通過Http和Websockets的方式和Jupyter Server進行互動,Jupyter Server和kernel之間,通過ZeroMQ進行資料通信,
Jupyter Server采用經典的MVC模式,使用了tornado作為web服務器,用來提供地址映射和控制器邏輯,使用jinja2來提供模板視圖功能,
Jupyter Notebook(v6.5.2)專案的主要模塊結構如下:
| 模塊 | 說明 |
|---|---|
| notebook | Notebook功能模塊, |
| terminal | 終端模塊,為Jupyter提供控制臺互動能力, |
| view | 檔案可視化模塊,比如pdf檔案的顯示, |
| tree | 作業區目錄樹 |
| nbconvert | 格式轉換模塊,可以把Jupyter Notebook轉換成html,pdf等格式 |
| kernel | Jupyter Notebook 內核 |
| services | Jupyter Notebook REST API模塊 |
| i18n | Jupyter Notebook多語言資源 |
3. 安裝Jupyter Notebook
前置條件
Python和pip
不同的Jupyter Notebook對Python有不同的版本要求,我們安裝的最新的穩定版本v6.5.2的Jupyter Notebook,要求Python的最低版本為3.6,注意這個Python的版本,不同于內核的Python版本,對于Jupyter內核來說,支持的Python版本和Jupyter Notebook依賴的Python版本沒有關系,
在Linux系統下安裝Jupyter Notebook
使用pip安裝Jupyter notebook非常簡單,如果服務器同時擁有Python2和Python3的pip,注意需要使用pip3來替換命令中的pip,
# 更新pip
pip install --upgrade pip
# 安裝jupyter
pip install jupyter
# 檢查安裝的jupyter
jupyter --version
//輸出 notebook : 6.5.2
4. 配置和啟動Jupyter
Jupyter提供了大量的啟動引數,用來配置Jupyter Server,我們可以在啟動Jupyter服務時,通過命令列引數的方式配置當前啟動的服務,但更普遍的方式是使用Jupyter的組態檔,
# 生成組態檔
jupyter notebook --generate-config
// 默認生成的組態檔位置:
/root/.jupyter/jupyter_notebook_config.py
# 修改Jupyter組態檔...
# 啟動jupyter
jupyter notebook
Jupyter直接使用一個Python檔案來配置Jupyter服務,所有的配置項均通過Python代碼來完成,常用的配置項及其說明如下:
| 名稱 | 默認值 | 說明 |
|---|---|---|
| c.NotebookApp.allow_root | False | 為了安全,Jupyter默認不允許使用root用戶啟動,如果需要以root用戶的身份啟動Jupyter,需要開啟此設定 |
| c.NotebookApp.allow_origin | '' | 當需要Jupyter內嵌到iframe時,可以設定為“*“來避免跨origin的限制 |
| c.NotebookApp.ip | localhost | 當需要通過外網地址來訪問Jupyter服務時,需要設定一個有效的服務器IP地址, |
| c.NotebookApp.port | 8888 | Jupyter server對外服務埠 |
| c.NotebookApp.notebook_dir | / | Jupyter的作業空間,默認可以訪問服務器上當前用戶的所有檔案系統 |
| c.NotebookApp.open_browser | True | 啟動服務后是否立即通過瀏覽器打開服務地址 |
| c.NotebookApp.default_url | /tree | Jupyter服務的默認地址 |
| c.NotebookApp.extra_static_paths | [] | 擴展靜態檔案目錄 |
| c.NotebookApp.extra_template_paths | [] | 擴展模板檔案目錄 |
| c.KernelSpecManager.allowed_kernelspecs | set() | 默認允許使用所有的kernel |
| c.NotebookApp.nbserver_extensions | {} | 允許加載的Jupyter Server擴展 |
5. 使用Jupyter
5.1. 創建Notebook
啟動Jupyter 后,在瀏覽器內輸入 http://服務器地址:埠/,Jupyter會默認重定向到.default_url指定的作業區目錄樹地址,默認是作業區目錄樹的界面,
如果在訪問的程序中,使用了默認的token作為其認證方式,那么在首次打開時,需要輸入Jupyter Notebook的token值,這個值可以在啟動Jupyter時的控制臺輸出中找到,或者使用Jupyter命令來查詢
# 查詢運行的jupyter notebook
jupyter notebook list
//回傳結果中包含了http://x.x.x.x:8899?token=ABC 的資訊,其中的ABC就是我們需要的token
圖3 Jupter Notebook的默認作業區目錄樹頁面
Jupyter Notebook通過Jupyter Server提供基于Web的平臺無關的作業方式,這使得跨平臺開發和協作,代碼分享等能力變得比傳統IDE更加容易,
在Jupyter 作業區管理界面,用戶可以靈活地以類似檔案系統的方式管理作業區的資料,可以創建檔案和檔案夾,編輯檔案和檔案夾,可以上傳和下載檔案,通過選擇一個Jupyter內核,可以創建一個Notebook檔案,
圖4 通過Jupyter內核創建一個Notebook
5.2. 使用Notebook
使用Python3內核創建一個Notebook后,我們得到一個xxx.ipynb(IPython Notebook)檔案,這個檔案是一個json格式的文本檔案,其中包含了我們在Notebook中撰寫的代碼和文本內容,也包含了界面上沒有顯示的元資料資訊,通過在作業區目錄界面選擇一個notebook檔案,點擊編輯,我們可以查看到ipynb檔案的原始內容,
圖5 ipynb檔案的原始內容
我們可以像使用其它IDE類似的方式來使用Notebook,在使用Notebook上,我們主要關注下Jupyter內核和單元格,
內核是執行單元格代碼的核心行程,不同的內核,決定了我們在單元格中能夠撰寫哪些語言的代碼,以及對應了指定的編程語言的哪個版本等資訊,
單元格是整個Notebook的核心組成部分,我們撰寫的代碼和文本,通過一些列Notebook單元格來組成,Notebook提供了Code,Markdown, Raw NBConvert, Heading四種型別的單元格,
?Code單元格,用來撰寫內核指定語言的程式代碼
?Markdown單元格,使用Markdown編輯器的語法來編輯富文本
?Raw NBConvert單元格,原始的文本,不會被當作代碼或markdown被解釋執行
?Heading單元格,Heading是Mardown的一個子集,對應了Markdown中的標題撰寫語法
Jupyter Notebook使用了機器學習中檢查點的概念,在我們修改Notebook的程序中,Jupyter會自動保存我們的修改,我們也可以通過【檔案】->【保存】來手動保存檢查點,檢查點檔案包含了我們撰寫的Notebook內容,以及執行代碼單元格之后的輸出,我們可以在作業空間的“.ipynb_checkpoints”檔案夾下,找到這些檢查點檔案,
圖6 使用Jupyter單元格來撰寫互動式代碼
5.3. 分享Notebook
相較于使用傳統的IDE撰寫的代碼,基于Web服務的Jupyter Notebook在代碼分享上擁有著天然的優勢,
在Jupyter Notebook中,我們可以通過兩種不同的方式分享我們創作的nootbook,
- 互動式Notebook檔案
傳統的技術檔案或者說明書,通過靜態的文本,配合圖片和視頻,來描述和講解特定的技識訓功能,有了Jupyter Notebook后,我們仍然可以使用Notebook來撰寫類似傳統的技術檔案,在此基礎上,我們可以加入更生動的代碼互動單元格,用戶通過查看檔案說明,并與檔案中提供的代碼進行互動,可以更生動地介紹產品中的功能和技術,每個Jupyter Notebook的ipynb檔案,都對應了一個獨立的訪問地址: http://x.x.x.x:8899/notebooks/my_notebook.ipynb ,通過分享此檔案的地址,其他用戶可以方便地使用包含了富文本和可執行的代碼的互動式Notebook檔案,
- 離線Notebook檔案
我們通過逐步執行檔案中的所有單元格,得到一個包含了我們撰寫的說明和代碼,以及代碼執行的輸出結果的完整檔案,之后點擊【檔案】-> 【另存為】,選擇一種合適的檔案格式,我們可以把檔案匯出為一份靜態檔案,通過共享此靜態檔案,我們實作了Notebook檔案的離線分享,
5.4. 魔法函式
Jupyter Notebook提供了一些列魔法函式來增強Jupyter Code單元格的功能,通過魔法函式,我們能夠執行javascript腳本,html代碼,運行另一個可執行程式等許多額外的功能,
我們可以在Jupyter代碼單元格中使用 %lsmagic命令來查看所有的魔法函式,如果要閱讀詳細的魔法函式的使用說明,可以參考: https://ipython.readthedocs.io/en/stable/interactive/magics.html
魔法函式分為行魔法函式,單元格魔法函式和會話魔法函式,顧名思義,行魔法函式只對當前行起作用,而單元格魔法函式則作用于整個單元格,會話魔法函式則作用于整個會話期間,
一些常用的魔法函式:
| 指令 | 說明 |
|---|---|
| %matplotlib | 設定matplot繪圖的顯示模式 |
| %%javascript | 單元格內的代碼被識別為javascript代碼 |
| %%html | 單元格內的代碼被識別為html代碼 |
| %run | 執行外部腳本檔案 |
| %pwd | 獲取當前作業的目錄位置(非作業空間目錄位置) |
| %writefile | 以檔案形式保存當前單元格代碼 |
| %timeit | 獲取本行代碼的執行時間 |
| %debug | 激活除錯模式 |
6. 管理Jupyter
6.1. 多語言
Jupyter Notebook使用i18n目錄下的資源來進行多語言翻譯,在Jupyter Notebook啟動時,會加載i18n目錄下的多語言資源,之后根據http請求指定的語言,為回應資料提供對應的多語言翻譯,如果沒有對應的翻譯,則保留原始的多語言標簽值(英文),如果調整了多語言翻譯,需要重新啟動Jupyter Notebook才能使用新的語言包,
Jupyter Notebook的翻譯資源主要分布在三個po檔案中:
?nbjs.po - js檔案中的多語言資料
?nbui.po - UI界面中的多語言資料
?notebook.po - notebook中的多語言資料
原始的po檔案,需要通過pybabel工具,把po檔案編譯成mo檔案,之后部署在$notebook/i18n/${LANG}/LC_MESSAGES/目錄下($notebook是notebook的安裝目錄),才能在Jupyter Notebook中作為多語言的資源包來使用,
# 使用pybabel編譯多語言po檔案
pybabel compile -D notebook -f -l ${LANG} -i ${LANG}/LC_MESSAGES/notebook.po -o ${LANG}/LC_MESSAGES/notebook.mo
pybabel compile -D nbui -f -l ${LANG} -i ${LANG}/LC_MESSAGES/nbui.po -o ${LANG}/LC_MESSAGES/nbui.mo
pybabel compile -D nbjs -f -l ${LANG} -i ${LANG}/LC_MESSAGES/nbjs.po -o ${LANG}/LC_MESSAGES/nbjs.mo
圖7 使用了中文語言包后的中文Notebook界面
6.2. 內核管理
內核(kernel)是獨立于jupyter服務和界面之外的用來運行Jupyter代碼單元格的行程,Jupyter默認提供了ipykernel內核來支持Python開發語言,Jupyter社區提供了jupyterC, IJava,xeus-cling, xeus-sql等眾多其它編程語言的內核,用來支持C/C++, Java, SQL等編程語言,
ipykernel默認使用系統環境下的Python來提供服務,我們可以使用ipykernel安裝多個Python kernel來提供Python2.x, Python3.x等多個Python內核環境,
安裝kernel后,kernel的資訊被保存在kernel.json檔案中,我們可以在 /usr/local/share/jupyter/kernels 目錄,找到Jupyter安裝的所有kernel以及對應的kernel.json檔案,
kernel可以直接繼承自安裝kernel的Python指令,也可以使用Python虛擬環境,
# 1.直接繼承自Python指令的kernel安裝
# 安裝ipykernel
pip install ipykernel
# 安裝kernel
python -m ipykernel install --name tensorflow2 --display-name "tensorflow2"
# 2. 在Python虛擬環境下的kernel安裝
# 激活虛擬環境
source activate myenv
# 安裝ipykernel
pip install ipykernel
# 安裝kernel
python -m ipykernel install --name myenv --display-name "Python3 (myenv)"
如果需要查看當前的kernel串列,以及洗掉已經安裝的kernel,可以使用如下的Jupyter命令:
# 查看已經安裝的kernel串列
jupyter kernelspec list
# 洗掉串列中指定的kernel
jupyter kernelspec remove kernelname
6.3. REST API
Jupyter提供了REST API介面來和Jupyter server進行互動,借助REST API的能力,我們可以以編程的方式和Jupyter Server進行互動,靈活地管理Jupyter Server,另外REST API為現代化的軟體開發提供了一個優秀的能力:自動化,
借助Jupyter Notebook REST API,可以實作檔案的上傳和下載,檢查點管理,會話管理,內核管理,終端管理等一些列管理能力,完整的Jupyter REST API介面串列可以參考: https://jupyter-server.readthedocs.io/en/latest/developers/rest-api.html
要使用REST API,需要在請求中攜帶認證資訊,Jupyter支持直接把token作為query string的方式來認證,也可以使用標準的Http Authorization頭資訊來完成認證,使用Authorization頭來認證的格式如下:
Authrozation: token 527a9f1430ccfed995ebcf15517583a2547c2469bc3c47a6
圖8 使用Postman來呼叫Jupyter REST API介面
6.4. 安全管理與多人協作
Jupyter提供了靈活強大的能力,用以支持在線的互動式檔案和代碼的撰寫,但Jupyter專案自身沒有提供精細化的安全管理體系,用以支持多用戶下靈活地使用Jupyter Notebook的功能,對于檔案安全,Jupyter依賴于啟動服務的linux用戶,合理地配置啟動Jupyter的用戶的權限,才能保證使用Jupyter的用戶,不會對系統或專案造成破壞,Jupyter作業空間的設定,僅起到了方便Jupyter使用者管理必要檔案的易用性,不能阻擋用戶訪問和管理作業空間外的檔案系統,另外,配合使用Python虛擬環境,可以防止Jupyter Notebook提供的 pip install ,pip uninstall功能,對現有專案環境造成破壞,
在多人協作方面,JupyterHub專案提供了多人協作Jupyter Notebook和Jupyter lab開發的能力,使用JupyterHub,不同職能的用戶可以在自己獨立的空間內進行Notebook的撰寫作業,不同用戶間也可以方便地分享各自的Notebook,
7. 擴展Jupyter
7.1. 前端擴展
Jupyter Notebook前端擴展(front end extension)是使用Javascript語言撰寫的異步模塊,可以用來繪制Jupyter界面的儀表盤,Notebook,工具列等,,定義一個前端擴展必須要實作一個load_ipython_extension方法,當前端控制元件被加載時,Jupyter client會呼叫load_ipython_extension方法,
Jupyter Notebook前端擴展能力目前還不是一個穩定的版本,不保證代碼能夠向后兼容,Jupyter的JS API目前也沒有官方的檔案,需要通過源代碼或者實際加載的JS來查看Jupyter前端腳本的成員和方法,
我們實作一個簡單的前端擴展腳本,在jupyter前端的工具條中,添加一個自定義工具,當點擊自定義工具時,彈出提示資訊,
define([
'base/js/namespace'
], function(
Jupyter
) {
function load_ipython_extension() {
var handler = function () {
alert('歡迎使用前端擴展!');
};
var action = {
icon: 'fa-comment-o',
help : '前端擴展',
help_index : 'zz',
handler : handler
};
var prefix = 'my_extension';
var action_name = 'show-alert';
var full_action_name = Jupyter.actions.register(action, action_name, prefix); // returns 'my_extension:show-alert'
Jupyter.toolbar.add_buttons_group([full_action_name]);
}
return {
load_ipython_extension: load_ipython_extension
};
});
完前端擴展代碼后,我們把腳本保存到main.js檔案,放置在/opt/my_extension目錄下,接下來我們使用jupyter nbextension工具來安裝和啟用前端擴展
# 安裝前端擴展
jupyter nbextension install /opt/my_extension
# 啟用前端擴展
jupyter nbextension enable my_extension/main
# 禁用前端擴展
jupyter nbextension disable my_extension/main
# 查看前端擴展串列
jupyter nbextension list
# 卸載前端擴展
jupyter nbextension uninstall my_extension
圖9 在Notebook工具條中加入的前端擴展
7.2. 服務端擴展
Jupyter服務端擴展(server extension)是使用Python語言撰寫的模塊,可以用來處理發送到Jupyter Server的Http請求,使用Jupyter服務端擴展,可以更改現有Jupyter請求的資料和行為,也可以為jupyter Server定義新的服務處理程式,
定義一個服務端擴展模塊要實作一個load_jupyter_server_extension方法,其中包含一個型別為notebook.notebookapp.NotebookApp的引數serverapp,serverapp的詳細屬性和方法可以通過Jupyter Notebook源代碼中的notebookapp.py檔案來查看,當服務端擴展被加載時,Jupyter Server會呼叫load_jupyter_server_extension方法,在load_jupyter_server_extension方法中,我們可以通過呼叫serverapp的web_app屬性的add_handlers方法來注冊處理程式,用來處理特定的服務端請求,處理程式類需要繼承自Jupyter的IPythonHandler類,在處理程式的方法中,可以使用Jupyter提供的@web.authenticated裝飾器來為方法增加身份認證保護,
通過服務端擴展,還可以與前端擴展聯動,實作一個功能豐富的Jupyter Notebook前端控制元件,
# 定義一個處理程式
from tornado import (
gen, web,
)
from notebook.base.handlers import IPythonHandler
class HelloWorldHandler(IPythonHandler):
@web.authenticated
@gen.coroutine
def get(self):
self.finish(f'Hello, world!')
# 實作load_jupyter_server_extension方法并注冊處理程式
def load_jupyter_server_extension(serverapp):
handlers = [
('/myextension/hello', HelloWorldHandler)
]
serverapp.web_app.add_handlers('.*$', handlers)
完成服務端擴展代碼后,我們把代碼保存為__init__.py檔案,要在Jupyter Notebook中使用處理程式,我們還需要進行服務端擴展的安裝和啟用,不同于前端擴展,服務端擴展不能直接使用指令來安裝,需要我們手動撰寫安裝程式,此外,Jupyter提供了自動啟用服務端擴展和前端擴展的方法,需要我們在腳本的根目錄提供啟用擴展的組態檔,
jupyter-config/
├── jupyter_notebook_config.d/
│ └── my_server_extension.json
└── nbconfig/
└── notebook.d/
└── my_front_extension.json
setup.py
加入了自動啟用擴展的配置,我們的服務端擴展目錄結構如下:
hello-extension/
├── __init__.py
jupyter-config/
├── jupyter_notebook_config.d/
└── hello_extension.json
hello_extension.json檔案的內容為:
{
"ServerApp": {
"jpserver_extensions": {
"hello_extension": true
}
}
}
接下來我們通過安裝程式,安裝服務端擴展的資訊保存在/root/.jupyter/jupyter_notebook_config.json檔案中,在安裝完成后,我們可以通過jupyter serverextesion工具來股那里服務端擴展
# 啟用服務端擴展
jupyter serverextension enable hello_extension
# 禁用服務端擴展
jupyter serverextension disable hello_extension
# 服務端擴展直接卸載的方法,需要我們通過pip uninstall 卸載安裝程式,
# 再通過手工修改/root/.jupyter/jupyter_notebook_config.json檔案洗掉擴展資訊來完成卸載
圖10 在瀏覽器中測驗安裝的服務端擴展程式
7.3. 界面定制
Jupyter沒有提供標準的界面定制的能力,但我們可以手工調整jupyter生成的模板視圖檔案和樣式檔案,達到整條調整jupyter notebook的界面的能力,
Jupyter Notebook模板檔案的位置為:$notebook/templates,樣式和腳本定制推薦的方案是使用/.jupyter/custom/custom.css和/.jupyter/custom/custom.js檔案,我們可以直接在此基礎上對檔案進行修改,還可以通過extra_template_paths和extra_static_paths來引入其它位置的模板和其它靜態檔案,
圖11 通過直接調整模板檔案加入的界面定制按鈕
7.4. 小部件
小部件(Widgets)是Jupyter互動式可視化資料呈現部件,Jupyter Widgets同時包含了訪問后端資料和前端呈現的能力,可以用于在Jupyter Notebook上生動地展示服務端的資料和資料變化,
在v6.5.2穩定版本上,我們目前只能使用系統提供的小部件,還不能開發自定義小部件,在Jupyter notebook7.x版本中,開始提供了小部件的自定義開發能力,
# 確保安裝了ipywidgets和traitlets
pip install --upgrade traitlets
pip install --upgrade ipywidgets
# 安裝和啟用小部件
jupyter nbextension install --py widgetsnbextension
jupyter nbextension enable --py widgetsnbextension
在安裝和啟用了小部件后,我們可以在notebook中直接使用系統提供的小部件,
圖12 在Notebook中使用小部件
完整的小部件串列和使用方式可以參考: https://ipywidgets.readthedocs.io/en/7.x/examples/Widget List.html
8. 總結
Jupyter Notebook以其豐富的功能,簡單易用,強大的互動能力和擴展能力,成為資料科學和機器學習開發中的神器,目前,Jupyter Notebook支持超過40種編程語言,被應用于Google Colab, Kubeflow, 華為云,kaggle等多個知名專案中,大量機器學習和資料科學的論文中使用到了Jupyter,Jupyter在資料可視化,提升作業效率,改善用戶體驗和豐富檔案功能方面顯現了巨大的威力,除此之外,Jupyter還提供的靈活強大的擴展能力,更是為Jupyter的深層次使用提供了更廣闊的想象空間,如果你還沒有開始接觸Jupyter,那么就從現在開始吧,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/541229.html
標籤:其他
上一篇:設計模式簡單介紹
下一篇:Auto-Job任務調度框架
