写点什么

可视化运行 Python 的神器 Jupyter Notebook

发布于: 2021 年 04 月 13 日

简介如果我们想要运行 Python,通常有两种方式,第一种方式就是在 Python 或者 IPython 的解释器环境中进行交互式运行,还有一种方式就是程序员最喜欢的编写.py 文件,在文件中编写 python 代码,然后运行。


如果我们想写一篇关于 Python 的文章,文章里面有代码,还希望代码能够在当前页面运行,可不可以做到呢?


可以的,那就是使用我们今天要介绍的 Jupyter Notebook。


Jupyter NotebookJupyter 项目是从 Ipython 项目中分出去的,在 Ipython3.x 之前,他们两个是在一起发布的。在 Ipython4.x 之后,Jupyter 作为一个单独的项目进行开发和管理。因为 Jupyter 不仅仅可以运行 Python 程序,它还可以执行其他流程编程语言的运行。


Jupyter Notebook 包括三个部分,第一个部分是一个 web 应用程序,提供交互式界面,可以在交互式界面中运行相应的代码。


上图是 NoteBook 的交互界面,我们可以对文档进行编辑,运行等操作。


主要的功能如下:


在浏览器中进行代码编辑,自动语法突出显示,缩进和制表符完成/自检功能。从浏览器执行代码的能力,并将计算结果附加到生成它们的代码上。


使用诸如 HTML,LaTeX,PNG,SVG 等富媒体表示来显示计算结果。例如,可以内嵌包含 matplotlib 库渲染的具有出版质量的图形。


使用 Markdown 标记语言在浏览器中对富文本进行的编辑(可以为代码提供注释)不仅限于纯文本。


使用 LaTeX 轻松在 markdown 单元中包含数学符号的能力,并由 MathJax 本地呈现。


第二个部分就是 NoteBook 的文档了,这个文档存储了要运行的代码和一些描述信息。一般这个文档是以.ipynb 的后缀进行存储的。


notebook 文档是以 json 的形式存储的,并用 base64 进行编码。使用 json 的好处就是可以在不同的服务器中方便的进行数据的交互。


Notebook documents 中除了可运行的代码文件,还可以存储说明等解释性内容,从而将代码和解释内容完美结合,尤其适合做学习笔记使用。


笔记本可以通过 nbconvert 命令导出为多种静态格式,包括 HTML,reStructuredText,LaTeX,PDF 等多种格式。


另外文档还可以方便的在网络上进行共享。


第三个部分就是代码运行的核心 Kernels,通过不同的 Kernels 搭配,notebook 可以支持运行多种程序。比如:Python,java,go,R,ruby,nodejs 等等。


这些 Kernels 和 notebook 之间是以 Json 的形式通过 MQ 来进行通信的。


启动 notebook server 有了文档之后,如果我们想要运行文档,需要启动 notebook server。


jupyter notebook 默认情况下会开启下面的 URL: http://127.0.0.1:8888


启动的时候还可指定要打开的.ipynb 文件:


jupyter notebook my_notebook.ipynb 具体的 notebook 界面的操作这里就不多介绍了,基本上和普通的编译器差不多。大家可以自行探索。


notebook document 的结构 notebook 中包含了多个 cells,每个 cell 中包含了多行文本输入字段,可以通过 Shift-Enter 或者工具栏中的播放按钮来执行其中的代码。


这里的 cell 有三种类型,分别是 code cells,markdown cells 和 raw cells。


code cells 代码单元允许您编辑和编写新代码,并突出显示完整的语法和制表符。 您使用的编程语言取决于内核,默认内核(IPython)运行 Python 代码。


执行代码单元时,它包含的代码将发送到与笔记本关联的内核。 然后,从该计算返回的结果将在笔记本中显示为单元格的输出。 输出不仅限于文本,还有许多其他可能的输出形式,包括 matplotlib 图形和 HTML 表格(例如,在 pandas 数据分析包中使用的表格)。


我们看一个 code cells 的例子:


#%%


import numpy as npmy_arr = np.arange(1000000)my_list = list(range(1000000))每个单元格是以 #%% 来进行分隔的。


Ipython 本身还支持多种富文本的展示格式,包括 HTML,JSON,PNG,JPEG,SVG,LaTeX 等。


Ipython 提供了一个 display 方法,我们可以使用 display 来展示要呈现的对象:


from IPython.display import displaydisplay(obj) 将会寻找这个对象所有可能的展示类型,并从中挑选一个最适合的类型进行展示,并将结果存储在 Notebook 文档里面。


如果你想展示特定类型的对象,那么可以这样:


from IPython.display import (display_pretty, display_html, display_jpeg,display_png, display_json, display_latex, display_svg)举个展示图片的例子:


from IPython.display import Imagei = Image(filename='../images/ipython_logo.png')idisplay(i)上面的例子中 i 包含了一个 Image 对象,直接调用 i 即可展示,我们也可以显示的调用 display(i)。


其他的富文本类型可以参考 Image,使用方法都是类似的。


markdown cellsmarkdown 是一种简介的标记语言,使用起来非常简单,使用范围非常广泛,所以 notebook document 也支持 markdown 的语法。


先看一个 markdown cell 的例子:


#%% md


$ pythonPython 3.6.0 | packaged by conda-forge | (default, Jan 13 2017, 23:17:12)[GCC 4.8.2 20140120 (Red Hat 4.8.2-15)] on linuxType "help", "copyright", "credits" or "license" for more information.>>> a = 5>>> print(a)5
复制代码


markdown 中的语法在 notebook 中都是可以用的。


还支持标准的 LaTeX 和 AMS-LaTeX 语法。


raw cells 原始单元格提供了一个可以直接写入输出的位置。 notebook 不会对原始单元格中的内容进行计算。


以模块的形式导入 Jupyter Notebooks 有时候我们希望以模块的形式导入 Jupyter Notebooks,但是可惜的是,Jupyter Notebooks 并不是一个标准的 python 程序,不过 Python 提供了一些钩子程序,让我们能够方便的进行导入。


首先,我们需要导入一些基本的 API :


import io, os, sys, types


from IPython import get_ipythonfrom nbformat import readfrom IPython.core.interactiveshell import InteractiveShell 接下来需要注册 NotebookFinder 到 sys.meta_path:


sys.meta_path.append(NotebookFinder())这个 NotebookFinder 就是定义的钩子。


我们看下 NotebookFinder 的定义:


class NotebookFinder(object):"""Module finder that locates Jupyter Notebooks"""def init(self):self.loaders = {}


def find_module(self, fullname, path=None):    nb_path = find_notebook(fullname, path)    if not nb_path:        return
key = path if path: # lists aren't hashable key = os.path.sep.join(path)
if key not in self.loaders: self.loaders[key] = NotebookLoader(path) return self.loaders[key]
复制代码


里面使用了两个重要的方法,find_notebook 用来找到 notebook,和 NotebookLoader,用来加载 notebook。


看下 find_notebook 的定义:


def find_notebook(fullname, path=None):"""find a notebook, given its fully qualified name and an optional path


This turns "foo.bar" into "foo/bar.ipynb"and tries turning "Foo_Bar" into "Foo Bar" if Foo_Bardoes not exist."""name = fullname.rsplit('.', 1)[-1]if not path:    path = ['']for d in path:    nb_path = os.path.join(d, name + ".ipynb")    if os.path.isfile(nb_path):        return nb_path    # let import Notebook_Name find "Notebook Name.ipynb"    nb_path = nb_path.replace("_", " ")    if os.path.isfile(nb_path):        return nb_path
复制代码


看下 NotebookLoader 的定义:


class NotebookLoader(object):"""Module Loader for Jupyter Notebooks"""def init(self, path=None):self.shell = InteractiveShell.instance()self.path = path


def load_module(self, fullname):    """import a notebook as a module"""    path = find_notebook(fullname, self.path)
print ("importing Jupyter notebook from %s" % path)
# load the notebook object with io.open(path, 'r', encoding='utf-8') as f: nb = read(f, 4)

# create the module and add it to sys.modules # if name in sys.modules: # return sys.modules[name] mod = types.ModuleType(fullname) mod.__file__ = path mod.__loader__ = self mod.__dict__['get_ipython'] = get_ipython sys.modules[fullname] = mod
# extra work to ensure that magics that would affect the user_ns # actually affect the notebook module's ns save_user_ns = self.shell.user_ns self.shell.user_ns = mod.__dict__
try: for cell in nb.cells: if cell.cell_type == 'code': # transform the input to executable Python code = self.shell.input_transformer_manager.transform_cell(cell.source) # run the code in themodule exec(code, mod.__dict__) finally: self.shell.user_ns = save_user_ns return mod
复制代码


有了他们,我们就可以直接 import 我们自己编写的 notebook 了。


本文已收录于 http://www.flydean.com/12-jupyter-notebook/


最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!


欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

发布于: 2021 年 04 月 13 日阅读数: 52
用户头像

关注公众号:程序那些事,更多精彩等着你! 2020.06.07 加入

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧,尽在公众号:程序那些事!

评论

发布
暂无评论
可视化运行Python的神器Jupyter Notebook