盐城市网站建设_网站建设公司_HTML_seo优化
2025/12/23 10:57:59 网站建设 项目流程

Jupyter Notebook 这个名字,很多人第一次听到,会把它当成一个写 Python 的工具。其实它更像是一种交互式计算文档的思想落地:把可运行的代码、代码运行后的输出、解释性的文字、公式、图表、图片乃至交互控件,装进同一份文档里,让读者既能阅读叙事,也能复现实验与推导。官方对它的经典描述是:它是一套基于 Web 的交互式计算环境,用来创建与分享计算型文档,文档里可以同时包含 Live code、叙事文本、公式与可视化等内容。 (jupyter.org)

很多软件把自己叫做notebook,但 Jupyter Notebook 的独特之处在于它既是一种文件格式与规范,也是一整套围绕这份规范构建的生态。Project Jupyter本身是一个伞状项目,覆盖了 Notebook、JupyterLab、内核协议、文件格式等多个子项目,核心目标是为计算型笔记本提供工具与标准。 (docs.jupyter.org)


名字从哪里来,为什么它不只服务于 Python

Jupyter 的命名很有工程师的幽默感:它既是 Julia、Python、R 三种语言名字的组合梗,也借用了伽利略在木星观测记录里写笔记的意象。更重要的是,这个名字背后暗示了一个转向:Notebook 不再被限定为Python 专属,而是面向多语言的交互式计算载体。 (Jupyter Blog)

在实际使用里,你会看到 Jupyter 支持几十种语言的内核实现,常见的包括 Python、R、Julia、Scala 等。Jupyter 官方站点也强调它支持 40 多种编程语言。 (jupyter.org)


把它说清楚:Jupyter Notebook 到底是什么

从工程视角看,Jupyter Notebook这四个字经常指向三层含义,混在一起就容易产生误解。

一层是文档本身:磁盘上的一个.ipynb文件。它不是神秘二进制,而是一个结构化的JSON文档,里面按单元格 cell组织内容:代码、文本、输出、元数据都在里面。Jupyter 的架构文档明确写到:Notebook 保存到磁盘时使用.ipynb扩展名,并采用JSON结构。 (docs.jupyter.org)

一层是编辑与展示界面:你在浏览器里看到的经典 Notebook 界面,或更现代的 JupyterLab。JupyterLab 被官方定位为下一代 Web 交互式界面,它把 Notebook、文本编辑器、终端、文件浏览器等多种工作流统一在一个可扩展的界面里。 (jupyterlab.readthedocs.io)

一层是运行时系统:负责管理文件、会话与内核的服务器进程,以及执行代码的内核进程。你在界面里按下运行,其实是前端把请求发给服务器,服务器再把请求转交给内核执行。

把这三层拆开理解,你就能明白很多日常现象:为什么关掉浏览器标签页,代码可能还在跑;为什么复制一个.ipynb文件给别人,他打开后图表可能不显示或提示不受信任;为什么同一个 Notebook 文件,既可以用经典界面打开,也可以用 JupyterLab 打开。


核心机制:cell、kernel、server 三者如何协作

cell:文档的基本粒度

Notebook 里的内容以 cell 为基本单位。常见类型是:

  • Code cell:可以执行代码,并把输出挂在这个 cell 下面
  • Markdown cell:写解释文字、公式、图片链接等
  • Raw cell:原样文本,常用于导出流程的特殊控制

这种组织方式让 Notebook 兼具源码报告的属性。它不是把代码粘贴进 Word,也不是在 IDE 里写一堆注释,而是把叙事与计算绑定在同一个可执行上下文里。

kernel:真正执行代码的进程

Kernel 是计算的心脏。你运行的代码并不是在浏览器里跑,而是在某个内核进程里跑。前端与内核之间靠消息协议通信:前端发执行请求,内核回执行结果、标准输出、错误栈、富媒体输出等。

Jupyter 的消息协议文档描述了客户端与内核之间的通信规范,并指出它们通过ZeroMQ等传输机制实现。 (jupyter-client.readthedocs.io)

server:连接浏览器与内核的桥梁

浏览器不直接连ZeroMQ,因为浏览器环境里做这种套接字通信不现实。Jupyter Server 的文档把这件事说得很直白:内核用ZeroMQ套接字通信,而 Web 应用侧使用WebSocket,服务器负责在两边转发消息。 (Jupyter Server)

这也解释了为什么你可以在远程服务器上跑内核,在本机浏览器里交互:浏览器只需要能访问服务器的HTTP/WebSocket端口。


.ipynb文件里装了什么:可读的 JSON 与 nbformat 规范

.ipynb的底层是JSON,并由nbformat规范定义。规范文档强调:Notebook 是简单的JSON文档,包含文本、源代码、富媒体输出与元数据,每一段都以 cell 形式存储。 (nbformat.readthedocs.io)

你可以把它理解成一个带版本号的结构化文档协议。它大致包含:

  • cells:每个 cell 的类型、源码、输出、元数据
  • metadata:内核信息、语言信息、扩展记录等
  • nbformatnbformat_minor:格式版本

这种设计带来很多好处:生态工具能读写同一格式;Notebook 能被转换成HTMLPDFMarkdown;也能被程序自动生成与批量执行。代价也很明显:JSON文件对Git diff不友好,输出里如果包含大段二进制编码或富媒体,会让版本库膨胀,合并冲突也更难处理。后面我会给一些工程化解法。


运行模型的真实面貌:它是有状态的交互式 REPL,而不是脚本

很多人用 Notebook 踩坑,根子不在语法,而在运行模型。

Notebook 的内核是一个长期存活的进程,行为更接近增强版 REPL:你可以反复运行某个 cell,变量就覆盖;可以跳着执行,内存状态就变得像一锅汤;可以在上面 import 一堆东西,后面随意调用。

这种自由度适合探索与推导,但它和脚本一次性从上到下执行的心智模型不同。工程上想要让 Notebook 可靠,有几条很朴素但极其有效的习惯:

  • 在分享或提交前,用界面里的Restart Kernel然后Run All,确保从零状态也能跑通
  • 把关键参数集中在前面一两个 cell,减少到处散落的魔法数
  • 避免在不同 cell 里定义同名函数或同名变量却含义不同
  • 输出图表时尽量固定随机种子与版本信息,让结果更可复现

这些建议听起来像经验之谈,但它们都在对抗同一个问题:Notebook 的执行顺序与文档阅读顺序并不必然一致。


Jupyter Notebook 与 JupyterLab:界面之争背后的工作流差异

经典 Notebook 界面更文档导向,像一张不断延展的纸。JupyterLab 更像可组合的开发环境:左侧文件浏览器,右侧多标签工作区,Notebook、终端、编辑器、数据文件可以并排。官方文档强调 JupyterLab 是可扩展、集成式的工作环境,适合更复杂的工作流。 (jupyterlab.readthedocs.io)

在团队里常见的分工是:

  • 个人探索、写教程、写研究记录:Notebook 或 JupyterLab 都行,经典界面更轻
  • 需要终端、文件树、多个面板联动:JupyterLab 更顺手
  • 需要把 Notebook 变成给别人用的交互应用:会走到 Voilà 或类似方案

安全这件事别掉以轻心:能运行任意代码就意味着高权限风险

无论 Notebook 还是 Jupyter Server,本质上都是远程代码执行环境。文档里写得非常直接:访问 Jupyter Server 就意味着能够运行任意代码,因此必须限制访问,默认启用基于 token 的认证。 (Jupyter Server)

另一个经常被忽略的点是 Notebook 的信任机制。Notebook 文件里可以包含HTMLJavaScript输出,如果你从别人那里拿到一个.ipynb,直接打开并显示这些输出,就可能产生跨站脚本或更复杂的攻击面。经典 Notebook 的安全文档描述了签名校验机制:服务器会计算 Notebook 的签名并与数据库比对,匹配则信任其HTMLJavaScript输出,否则以不受信任方式加载。 (jupyter-notebook.readthedocs.io)

工程上比较稳妥的做法是:

  • 不要把未审查的 Notebook 当成普通文档点开就看输出
  • 共享给他人前,尽量清理输出或用可信环境重新执行生成输出
  • 公网部署不要关认证,不要把服务裸露在互联网,必要时用反向代理与更严格的鉴权

生态工具链:Notebook 不止能手工点点点

nbconvert:把 Notebook 变成可交付物,也能批量执行

很多团队会把 Notebook 当作可执行报告:提交时不只给.ipynb,还会导出HTMLPDF作为交付件。nbconvert提供了执行 Notebook 并保存输出的能力,文档明确介绍了它可以执行.ipynb输入并把包含输出的结果保存为.ipynb。 (nbconvert.readthedocs.io)

ipywidgets:让 Notebook 从静态文档变成可交互实验台

如果你在 Notebook 里做参数敏感性分析,ipywidgets这种交互控件会很爽。官方文档把它定义为面向 Notebook 的浏览器交互控件,包含滑条、复选框、文本输入等,并强调交互控件能让 Notebook活起来。 (ipywidgets.readthedocs.io)

JupyterHub:把 Notebook 交给一群人用

课堂、企业数据团队、研究组常见需求是多人同时用同一套 Notebook 服务,但每个人又要隔离环境与资源。JupyterHub 的定位就是多用户 Hub,负责生成、管理、代理多个单用户 Notebook 服务器实例。 (JupyterHub)

Jupytext:用文本格式解决版本控制与 diff 痛点

.ipynbJSON,在Git里读起来费劲。Jupytext 的思路是把 Notebook 的输入内容保存成.py.md等纯文本,天然适合版本控制,并且可以选择与.ipynb配对。它的文档强调:文本 Notebook 很适合版本控制,输出默认不落盘,除非你选择与.ipynb配对。 (Jupytext)

Voilà:把 Notebook 变成一个真正给别人用的 Web 应用

当你的 Notebook 里有控件、有交互逻辑,你可能不想把代码 cell暴露给最终用户。Voilà 的文档与仓库介绍它可以运行、转换并把 Notebook 作为独立应用提供服务,并说明每个连接用户会获得独立的内核用于执行控件回调。 (voila.readthedocs.io)


一段可运行的完整示例:自动生成 Notebook、执行、导出 HTML

下面这段代码是一个完整脚本,做三件事:

  1. nbformat生成一个新的.ipynb
  2. nbconvert的执行预处理器把 Notebook 跑一遍并保存输出
  3. 导出成一个HTML文件,便于交付或归档

你只要装好依赖就能跑。依赖通常在安装 Jupyter 时就会带上,缺什么再补什么即可。

# 文件名: make_and_run_notebook.py# 运行: python make_and_run_notebook.py# 产物: demo_notebook.ipynb / demo_notebook.executed.ipynb / demo_notebook.htmlfrom__future__importannotationsfrompathlibimportPathimportnbformatfromnbformat.v4importnew_notebook,new_code_cell,new_markdown_celldefbuild_notebook()->nbformat.NotebookNode:nb=new_notebook()nb.cells.append(new_markdown_cell('# Demo: 在 Jupyter Notebook 里写一份可执行的小报告\n''\n''这份 Notebook 展示三件事:\n''- 代码与叙事文字放在同一份文档\n''- 运行代码产生输出\n''- 生成一张简单的图\n'))nb.cells.append(new_code_cell('import math\n''data = [math.sin(i / 10.0) for i in range(0, 100)]\n''summary = {\n'' \'count\': len(data),\n'' \'min\': min(data),\n'' \'max\': max(data),\n'' \'mean\': sum(data) / len(data),\n''}\n''summary\n'))nb.cells.append(new_markdown_cell('下面用 matplotlib 画一张曲线图。'))nb.cells.append(new_code_cell('import matplotlib.pyplot as plt\n''\n''plt.figure()\n''plt.plot(data)\n''plt.title(\'sin curve\')\n''plt.xlabel(\'index\')\n''plt.ylabel(\'value\')\n''plt.show()\n'))returnnbdefsave_notebook(nb:nbformat.NotebookNode,path:Path)->None:path.write_text(nbformat.writes(nb),encoding='utf-8')defexecute_notebook(src_path:Path,dst_path:Path,timeout:int=120)->None:fromnbconvert.preprocessorsimportExecutePreprocessor nb=nbformat.read(src_path,as_version=4)ep=ExecutePreprocessor(timeout=timeout,kernel_name='python3')# metadata.path 决定 Notebook 执行时的工作目录ep.preprocess(nb,{'metadata':{'path':str(src_path.parent)}})nbformat.write(nb,dst_path)defexport_html(nb_path:Path,html_path:Path)->None:fromnbconvert.exportersimportHTMLExporter nb=nbformat.read(nb_path,as_version=4)exporter=HTMLExporter()body,_resources=exporter.from_notebook_node(nb)html_path.write_text(body,encoding='utf-8')defmain()->None:out_dir=Path('.').resolve()src=out_dir/'demo_notebook.ipynb'executed=out_dir/'demo_notebook.executed.ipynb'html=out_dir/'demo_notebook.html'nb=build_notebook()save_notebook(nb,src)execute_notebook(src,executed)export_html(executed,html)print('generated:',src)print('executed :',executed)print('html :',html)if__name__=='__main__':main()

如果你本机缺依赖,可以这样装:

python -m pipinstallnbformat nbconvert matplotlib

跑完脚本后,你可以用JupyterLab或经典 Notebook 打开demo_notebook.executed.ipynb看运行后的输出;也可以直接用浏览器打开demo_notebook.html,把它当成一份可交付的静态报告。nbconvert能执行并保存 Notebook 输出这一点在它的文档里有明确说明。 (nbconvert.readthedocs.io)


它擅长什么,也不擅长什么

Notebook 最擅长的场景,是探索性计算解释性表达同时发生的地方:数据分析、科研推导、教学演示、实验记录、可视化报道、机器学习原型验证。它把思路证据放在一起,读者不需要脑补你怎么从 A 推到 B,因为 B 就是代码跑出来的输出。

但如果你把它当成大型软件工程的主战场,它的短板也会显出来:

  • 单个内核长期运行,状态复杂,容易出现只在我电脑上能跑
  • .ipynbJSON结构让代码评审与合并冲突变得笨重
  • 过度依赖交互,会让可复现与自动化流水线变得脆弱

这也是为什么成熟团队经常把 Notebook 定位为实验台可执行说明书,而把稳定的生产逻辑沉淀为包、模块、服务或工作流,再在 Notebook 里调用它们。用这种分层方式,Notebook 负责把复杂系统讲清楚,生产代码负责把系统跑稳定。


一点经验之谈:把 Notebook 用得更像工程,而不是临时草稿

  • 把关键逻辑做成可导入的模块,在 Notebook 里只做调用与展示
  • 输出与输入分离:Notebook 记录输入参数、运行步骤、图表结果,原始数据与模型权重用外部文件管理
  • Jupytext之类的工具把输入内容落到.py.md,降低Git审查成本 (Jupytext)
  • 共享时坚持用干净环境Restart+Run All,让读者拿到的是可复现的路径
  • 公网部署严格鉴权,默认 token 机制别关,别把能执行任意代码的入口当成普通静态网站 (Jupyter Server)

如果你愿意再往深处挖,我也可以把Jupyter的消息协议按一次真实的execute_requestiopub输出的链路画出来,配上一个最小内核与最小客户端示例,让你从协议层彻底吃透它为什么能支持多语言与多前端。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询