nbdev+Quarto:提高生产力的新秘密武器

我们提高软件工程生产力的首选工具 nbdev,现已使用 Quarto 重写
技术
作者

Hamel Husain 和 Jeremy Howard

发布日期

2022年7月28日

我们提高生产力的新秘密武器

今天,我们很高兴地宣布,我们已与 Quarto 携手,为 nbdev 赋予超能力。nbdev 为 Python 程序员提供了一套通用工具,用于使用 Jupyter Notebooks 进行:

  • 编写和分发软件包
  • 测试代码,以及
  • 撰写文档和技术文章

单个 notebook 可以创建 Python 模块、测试、持续集成 (CI)、pypi/conda 包等。

尽管 Notebooks 已经广泛用于一次性的探索性工作,但它们完全能够编写高质量的软件这一点鲜为人知。事实上,在过去三年中,我们已将 nbdev 用于各种软件项目,包括深度学习库API 客户端Python 语言扩展终端用户界面等等。我们发现,它不仅能够编写出色的软件,而且还将我们的生产力提高了 300% 或更多。使用 nbdev,开发人员只需使用轻量级标记编写 Notebooks,即可免费获得高质量的文档、测试、持续集成和打包!nbdev 使我们能够维护和扩展许多开源项目。拉取请求通常附带详细的文档和测试——贡献者只需编写 Notebooks 即可。

这就是我们很高兴分享 nbdev v2 的原因。它已从头开始重写,包含许多备受期待的功能,包括:

  • 与非 nbdev 代码库互操作,用于文档等任务
  • 支持任何静态站点生成器
  • 广泛的输出媒介,如博客、论文、幻灯片和网站
  • 更快的 Jupyter 内核,这也意味着更快的测试
  • 更清晰且可扩展的 API,支持自定义指令、自定义模块导出器等

nbdev 在工业中的应用

我们已在多家公司试用过 nbdev。我们很高兴收到以下反馈,这些反馈与我们自己使用和开发 nbdev 的经验相符:

David Berg,关于在 Netflix 使用 nbdev 进行内部文档编写:“在使用 nbdev 之前,文档编写是我们软件开发过程中最繁琐的方面……使用 nbdev 使我们能够花费更多时间围绕众多代码片段创建丰富的文本描述,从而确保整个体验的稳健性。nbdev 将曾经的苦差事变成了我们已经在进行的基于 Notebook 的测试的自然延伸。”

Erik Gaasedelen,关于在 Lyft 生产环境中使用 nbdev:“我在公司生产环境中使用它。这是一个很棒的工具……nbdev 简化了一切,因此我可以在一个地方编写文档、测试和代码……打包也非常周到。在我看来,这几乎是对传统 Python 库开发的帕累托改进。”

Hugo Bowne-Anderson,关于在 Outerbounds 使用 nbdev:“nbdev 改变了我们编写文档的方式。当我们 API 改变或[由于]将代码复制粘贴到 markdown 文件中导致人为错误而担心代码示例失效的日子一去不复返了。nbdev 的编写体验……[允许]我们在统一的界面中编写散文和实时代码,这允许进行更多实验……最重要的是,nbdev 允许我们在文档中包含单元测试,这减轻了随时间维护文档的负担。”

Roxanna Pourzand,关于在 Transform 使用 nbdev:“我们对使用 nbdev 感到非常兴奋。我们的产品是技术性的,因此生成的文档包含很多基于代码的示例。在 nbdev 之前,我们无法维护我们的代码示例,也无法确保命令输入和输出都能保持最新。这一切都是手动的。使用 nbdev,我们现在以可持续的方式控制了这一点。自从我们部署了这些文档以来,我们还遇到了一个情况,能够识别出我们一个接口中的错误,这是通过在文档中看到输出的错误发现的。”

什么是 nbdev?

nbdev 以传统 IDE 和软件开发工作流程无法实现的方式,拥抱 Python 的动态特性和 REPL 驱动的开发。三年前,我们在这篇最初的发布文章中详细讨论了 nbdev 的动机、历史和目标。Jupyter 的创建者 Fernando Pérez 告诉我们:

[nbdev] 应该得到更多的赞扬和使用——我的 Chrome 浏览器里已经把你们最初的 nbdev 博客文章的标签页打开了几个月,因为我经常会参考它并推荐给其他人。

简而言之,nbdev 借鉴了文学化编程探索性编程的思想。这些范式已在 XCode Playgrounds 等平台以及 Smalltalk、LISP 和 Mathematica 等语言中重新得到关注。借助 nbdev,我们希望通过将其应用于世界上最流行的动态编程语言之一:Python,来进一步推广这些范式。

Octoverse 2021 年报告,GitHub

尽管由于与 Jupyter Notebooks 集成,nbdev 在科学计算社区中应用最广泛,但我们发现 nbdev 非常适合更广泛的软件开发。我们已使用 nbdev 编写了深度学习库API 客户端Python 语言扩展终端用户界面等!

Hamel:当我使用 nbdev 时,我的同事经常惊讶于我创建和分发高质量 Python 包的速度。我认为 nbdev 是一种超能力,它允许我在没有任何额外障碍的情况下创建测试和文档,这使得我的所有项目都更容易维护。我还发现使用 nbdev 编写软件更有趣、更高效,因为相对于更传统的软件工程工作流程,我可以非常快速地迭代想法。最后,如果我想,使用 nbdev 我也可以使用传统的基于文本的 IDE,因此我可以兼得两者的优点。

使用 nbdev 三年后的心得

虽然 nbdev 最初是为了简化各种fast.ai 项目的软件开发工作流程而开发的,但我们发现用户希望将 nbdev 扩展到:

  • 使用 Jupyter Notebooks 编写和发布博客文章、书籍、论文以及其他类型的文档
  • 为非 nbdev 编写的现有代码库编写文档
  • 适应传统的 Python 约定——适用于那些在代码组织和格式方面受到约束的人
  • 使用任何静态站点生成器发布内容

虽然我们创建了诸如fastpagesfastdoc 等项目来完成其中一些任务,但我们意识到最好拥有一套灵活的工具来完成所有这些任务。为此,我们非常兴奋地发现了 Quarto,一个基于 pandoc 构建的开源技术出版系统。

Hamel:我使用 nbdev 创建 Python 模块越多,就越想用它来编写博客和记录现有代码库。定制 Notebook 渲染方式(隐藏或显示单元格、剥离输出等)的能力,以及包含单元测试的功能,使其成为我所有技术内容的首选创作工具。我很高兴 nbdev2 为每个人解锁了所有这些可能性!

Quarto 登场:一个 pandoc 超级处理器

Quarto 是一个支持 Jupyter Notebook、VSCode、Observable 和纯文本编辑器的技术出版项目。此外,Quarto 支持以 HTML、PDF、ePub、PowerPoint 幻灯片等格式发布高质量的文章、报告、网站和博客。RStudio(一家在支持文学化编程产品方面拥有悠久历史的公司,如 RMarkdown 和 RStudio)负责维护 Quarto。

Quarto 构建在 Pandoc 之上,Pandoc 是一个通用文档转换器,几乎支持你能想到的任何格式。Pandoc 通过在一个通用的抽象语法树(AST)中表示文档来实现这一看似神奇的壮举,AST 作为不同格式之间转换的媒介。由此引申,Quarto 允许你以几乎任何你想要的格式生成内容!你可以使用 pandoc 过滤器来修改 AST 和输出格式,这允许你使用任何你想要的静态站点生成器,并以编程方式修改和生成内容。

Quarto 允许你在处理管线中组合 pandoc 过滤器,并将其应用于特定文档或整个项目。你还可以将过滤器作为 Quarto 扩展分发,这使得 Quarto 具有极高的可定制性。

我们还发现 Quarto 令人信服,因为诸如注释指令(以 #| 开头的注释)之类的用户界面与 nbdev 相关。事实上,我们甚至了解到 nbdev 在这方面启发了 Quarto!总的来说,Quarto 和 nbdev 有许多共同目标,Quarto 团队对我们的建议反应非常迅速。例如,创建notebook 过滤器以在渲染前修改 notebook 的能力。下面是一张使用 Quarto 和 nbdev 渲染的 Jupyter notebook 的截图。

Quarto 渲染使用 nbdev 编写的 Jupyter notebook

最后,Quarto 支持的编程语言不仅限于 Python,并且正以令人印象深刻的速度添加新功能和修复错误。这让我们有信心在未来能够扩展 nbdev 以支持更多用例。我们在结尾部分讨论了其中一些未来的方向。

一个极速的 notebook 内核:execnb

nbdev 的一个核心组件是以编程方式执行和测试 notebook。重要的是,这个 notebook 运行器应以最小的开销执行,以保持我们提供愉悦的开发者体验的目标。这就是为什么我们构建了 execnb,一个轻量级的 Python 内核 notebook 运行器,它可以极速执行 notebook。此外,execnb 支持 notebook 的参数化执行。

Hamel:我一直是 papermill 等工具的热情用户,这些工具可以编程方式运行 notebook,用于诸如创建仪表板或启用新型机器学习工作流程等用例。我相信 execnb 凭借其在 notebook 的任何位置注入任意代码的能力,以及传递在单元格执行之前和/或之后运行的回调的能力,解锁了更多可能性。这为创建新型基于 notebook 的工作流程提供了可能性,我很高兴在不久的将来进行探索。

迈向一种拥抱其动态特性的 Python 方言

理解 nbdev 的一种方式是将其视为一个旨在拥抱 Python 动态特性以进行 REPL 驱动的软件工程的生态系统的一部分。类似于 Clojure,我们的目标是提供工具,消除在编程工作流程中使用 REPL 的所有障碍。我们相信 REPL 通过上下文敏感的自动完成、签名检查和文档(所有这些都基于代码的实际状态,而完全依赖静态分析的 IDE 中无法提供这些功能)来增强开发人员工作流程。基于这个原因,我们发现 nbdev 及其 Jupyter notebook 基础,使得编程效率显著提高且更令人愉快。

我们支持 REPL 驱动的开发和文学化编程的努力不仅限于 nbdev。我们维护了许多扩展 Python 的库,以增强这种编程体验。其中最值得注意的是 fastcore 库,它在测试代码文档元编程属性助手增强的对象表示以及 notebook 友好的补丁等方面扩展了 Python。这篇博客文章提供了 fastcore 的简要介绍。除了文学化编程,fastcore 还鼓励简洁和高效利用垂直空间等约定,这样你就能用更少的代码完成更多事情。例如,下面是一个简单的装饰器,它支持 notebook 友好的补丁功能:

@patch fastcore 中的装饰器

我们相信,这种新的开发者工作流程(nbdev)、Python 扩展(fastcore)及相关规范的组合,形成了一种新的 Python 方言,其核心在于利用其动态特性——这与日益增长的静态分析趋势形成对比。我们认为这种 Python 方言在许多场景下对程序员来说会更高效。我们将这个生态系统框定为一种“方言”,因为它仍然是 Python 的核心,任何熟悉该语言的人都可以上手。此外,尽管 nbdev 是基于 notebook 的工作流程,但我们的工具会生成纯文本模块,可以使用基于文本的 IDE 进行导航和编辑,如果程序员愿意,他们可以体验两者的最佳优点。

Hamel:我认为将 nbdev 视为一种 Python 方言是正确理解它的关键。虽然可能很容易陷入 nbdev 的特定功能或技术细节中,但最好放大视野,理解创建更好工作流程的整体意图,而不是过于僵化地遵循现有流程。一个很好的类比是 TypeScript 与 JavaScript 的关系:它是现有编程语言的扩展,支持一种新的编程方式。我鼓励你以类似的方式对待 nbdev:愿意尝试新的编程方式,并观察哪些权衡点与你契合。至少,我相信 nbdev 是一种体验不同软件编写方式的有趣方法,它将拓宽你对编程的总体视野,而且无需学习一门全新的编程语言!

nbdev 的未来

虽然我们对 nbdev2 感到兴奋,但我们相信我们才刚刚触及其潜力的表面。我们正在考虑以下功能:

  • 支持 Python 以外的更多语言,例如 Julia、R 和 JavaScript
  • 提供执行模拟 Python 脚本的参数化 notebook 的接口
  • 更多静态站点生成器和过滤器的扩展
  • 支持备用测试后端,例如 pytest
  • 支持更多文档字符串格式,例如Google 风格的文档字符串
  • 更多选项使用纯文本或人类可读的 notebook 后端(而非 JSON)

如果你对如何扩展 nbdev 有有趣的建议,请加入我们的 discord 聊天,或在论坛中发帖。

如何开始使用 nbdev

我们的项目网站是 nbdev.fast.ai,在接下来的日子里,我们将在那里发布教程、示例和更多文档。

感谢

这个新版本的 nbdev 是许多优秀人士共同努力的结果。我们想重点感谢两位做出了杰出贡献的人:

  • Wasim Lorgat 在多个领域发挥了关键作用,包括对 fastcore、execnb 和 nbdev 做出了重大贡献,以及实现了新的 nbdev 主页。在 Wasim 的帮助下,我们将 nbdev 的功能和质量提升到了新的水平。

  • JJ Allaire 不仅是 RStudio 的 CEO,也是 Quarto 的管理者。JJ 对我们的 nbdev 工作非常积极响应并渴望合作,他专门为 nbdev 在 Quarto 中添加了许多功能,例如notebook 过滤器。我们对他在细节上的关注以及解决 bug 的速度感到惊讶。没有 JJ 的帮助,这个新版本的 nbdev 是不可能实现的,我们很高兴继续与他合作。

我们还要感谢出色的 fastai 社区,特别是 Isaac FlathBenjamin WarnerZach Mueller 在这个项目上付出的不懈努力。

与 JJ Allaire 的对话

为了庆祝 nbdev v2 和 Quarto 的发布,Jeremy 与 Posit(以前称为 RStudio,Quarto 背后的公司)的 CEO JJ Allaire 进行了座谈,讨论了软件开发、科学出版、R、Python、文学化编程等等。