marimo 杂项 API 完全指南:`running_in_notebook`、`defs`/`refs`、`notebook_dir` 与 `mo.inspect()` 的实战运用
2026/9/13 18:13:47 网站建设 项目流程

marimo 杂项 API 完全指南:running_in_notebookdefs/refsnotebook_dirmo.inspect()的实战运用

【免费下载链接】marimoA reactive notebook for Python — run reproducible experiments, query with SQL, execute as a script, deploy as an app, and version with git. Stored as pure Python. All in a modern, AI-native editor.项目地址: https://gitcode.com/GitHub_Trending/ma/marimo

marimo 是一个"以纯 Python 存储、响应式运行"的交互式笔记本框架。除了mo.ui控件、mo.md排版和 SQL 支持等核心功能外,docs/api/miscellaneous.md 收录了一组散落在运行时与输出层的"杂项"但极其实用的 API:环境判定、单元格内省、文件路径定位与对象检视。本文以该文档为主线,逐一对mo.running_in_notebook()mo.defs()mo.refs()mo.notebook_dir()mo.notebook_location()mo.inspect()进行讲解,并结合仓库源码说明其底层实现,帮助你写出"既能在笔记本里跑、又能当脚本执行、还能部署成 App"的健壮代码。


一、运行环境判定:mo.running_in_notebook()

用法与语义

mo.running_in_notebook()返回一个布尔值:当前是否运行在 marimo 笔记本环境中。

import marimo as mo if mo.running_in_notebook(): print("当前运行在 marimo notebook 中") else: print("当前运行在普通 Python 脚本 / REPL 中")

这在编写"笔记本与脚本双兼容"的代码时非常关键。例如某些耗时操作(如启动进度条、渲染富文本输出)只在笔记本中有意义,而作为python script.py运行时希望走静默分支:

if mo.running_in_notebook(): progress = mo.ui.range_slider(0, 100, value=(0, 50)) progress else: # 脚本模式下直接使用默认参数 lo, hi = 0, 50

底层实现原理

源码位于 marimo/_runtime/context/utils.py:

@mddoc def running_in_notebook() -> bool: """Returns True if running in a marimo notebook, False otherwise""" try: ctx = get_context() except ContextNotInitializedError: return False else: from marimo._runtime.context.kernel_context import KernelRuntimeContext return isinstance(ctx, KernelRuntimeContext)

其判定逻辑分为两步:

  1. 上下文是否初始化:marimo 运行时会通过get_context()获取当前运行时上下文;若抛出ContextNotInitializedError(例如在普通 Python 解释器、pytest 或部分 CLI 场景下),直接返回False
  2. 上下文类型是否为KernelRuntimeContext:笔记本编辑/运行会话会建立 Kernel 运行时上下文,而脚本模式(ScriptRuntimeContext)和测试模式都不属于 Kernel 上下文,因此也会返回False

也就是说,该函数只对"真实的 marimo 笔记本会话"返回True,对marimo run、脚本执行、pytest 测试均返回False,语义非常明确。同文件中的get_mode()(返回"run"/"edit"/"script"/"test")则更进一步区分具体运行模式,两者可配合使用。


二、单元格自省:mo.defs()mo.refs()

marimo 的每个单元格都会先被静态分析(marimo/_ast 中的编译器与 visitor),从中提取两类信息:

  • defs(definitions):当前单元格定义/赋值的名字;
  • refs(references):当前单元格引用、但定义在其他地方的名字。

用法示例

import marimo as mo # 在本单元格中定义 x = 1 y = x + 1 # 查看当前单元格的 defs 与 refs print(mo.defs()) # ('x', 'y') print(mo.refs()) # ('x',) —— 取决于 x 是否在其它单元格中定义

典型应用场景是自省式调试:在一个单元格末尾打印出该单元格输出了哪些变量、依赖了哪些变量,快速核对数据流关系。也可以配合条件逻辑,根据"本单元格是否定义某变量"来决定后续分支。

源码实现细节

两个函数都定义在 marimo/_runtime/runtime.py:

@mddoc def defs() -> tuple[str, ...]: """Get the definitions of the currently executing cell...""" try: ctx = get_context() except ContextNotInitializedError: return () if ctx.execution_context is not None: cell_id = ctx.execution_context.cell_id if cell_id not in ctx.graph.cells: return () return tuple(sorted(defn for defn in ctx.graph.cells[cell_id].defs)) return ()

refs()的实现与之对称,但多了一步过滤:会剔除"未被用户遮蔽(shadowed)的内置函数名",即如果单元格引用了lenprint等内置函数,而图中又没有用户自定义的同名定义,则这些名字不会出现在返回元组中,避免噪音。

值得注意的几个行为特征:

  • 两者都返回排序后的元组,保证多次调用结果稳定;
  • 若上下文未初始化(ContextNotInitializedError),返回空元组(),因此mo.defs()/mo.refs()在脚本模式下也是安全的,不会抛异常;
  • 源码中专门处理了"scratchpad 单元格"(临时单元格):它不在主执行图中,此时同样返回空元组。

这些"图"信息正是 marimo 响应式调度的基础:运行时根据单元格的 refs 建立依赖边,再按拓扑序执行,详见 marimo/_ast/cell.py 与 marimo/_ast/visitor.py 中的提取逻辑。


三、路径定位:mo.notebook_dir()mo.notebook_location()

这两个函数解决一个非常实际的问题:"我的数据文件在哪里?"。笔记本文件可能被放在任意目录、通过marimo edit打开,也可能被部署为 WebAssembly 应用托管在网页上——硬编码相对路径很容易失效。

mo.notebook_dir():获取笔记本所在目录

返回pathlib.Path | None,即当前执行笔记本所在的目录(而非文件路径)。

import marimo as mo data_file = mo.notebook_dir() / "data" / "example.csv" if data_file.exists(): print(f"Found data file: {data_file}") else: print("No data file found")

源码(marimo/_runtime/runtime.py)揭示了它的健壮性设计:

try: ctx = get_context() except ContextNotInitializedError: # If we are not running in a notebook (e.g. exported to Jupyter), # return the current working directory return pathlib.Path().cwd()
  • 在笔记本中:读取运行时上下文中被 runner 注入的__file__(源码注释明确说明该变量"由 runner 修补,始终正确"),对其执行normalize_path并逐级向上取到目录;若文件名缺失则回退到上下文中的ctx.filename
  • 不在笔记本中(例如导出到 Jupyter 或脚本环境):直接返回当前工作目录pathlib.Path().cwd(),保证代码在笔记本之外依然可用,不会返回None

mo.notebook_location():兼容本地与 WebAssembly 的路径定位

返回pathlib.PurePath | None。它与notebook_dir的区别在于运行平台

  • WASM 环境(例如用marimo export后托管在 GitHub Pages 等静态站点,通过浏览器中运行的 Pyodide 执行):返回网页 URL,例如https://my-site.com;嵌套路径时返回"含 origin 与 pathname 的完整 URL",如https://<my-org>.github.io/<my-repo>/folder
  • 非 WASM 环境(本地笔记本):返回笔记本所在目录,与mo.notebook_dir()相同。

一个典型用途是"本地与 WebAssembly 双端都能读到数据":

import marimo as mo import polars as pl data_path = mo.notebook_location() / "public" / "data.csv" df = pl.read_csv(str(data_path)) df.head()

本地运行时它指向data/目录,WASM 运行时它指向静态站点上对应 URL,同一份代码两处通用。

源码(marimo/_runtime/runtime.py)中的关键逻辑:

if is_pyodide(): from js import location # type: ignore path_location = pathlib.Path(str(location)) # The location looks like https://.../notebooks/assets/worker-BxJ8HeOy.js # We want to crawl out of the assets/ folder if "assets" in path_location.parts: return URLPath(str(path_location.parent.parent)) return URLPath(str(path_location)) else: return notebook_dir()

这里还定义了一个URLPath(pathlib.PurePosixPath)子类,重写__str__以保留 URL 协议中的"://"不被pathlib吞掉,保证拼接后的路径仍是合法 URL。你可以在 docs/guides/wasm.md 进一步了解 WASM 部署方式,或在 examples/storage 中查看数据存取相关示例。


四、富文本对象检视:mo.inspect()

mo.inspect()用于以丰富、可交互的 HTML 形式展示任意 Python 对象的属性、方法与文档字符串。它尤其擅长处理那些没有好看repr的对象(如第三方库实例、配置对象),直接在单元格输出即可渲染。

基础用法

import marimo as mo # 检视一个类(methods=True 展开方法列表) mo.inspect(list, methods=True) # 检视一个实例 my_dict = {"key": "value"} mo.inspect(my_dict) # 显示全部属性,包括私有(_x)与双下划线(__x__)成员 mo.inspect(my_dict, all=True)

在单元格中直接写下mo.inspect(...)(作为单元格最后一个表达式)即可看到渲染结果:顶部是类型标签与对象名的头部(带色彩区分),下方依次是文档摘要、对象值/签名、以及按表格排布的属性列表。

完整参数说明

mo.inspect()是一个Html子类(实现位于 marimo/_plugins/stateless/inspect.py),构造签名如下:

mo.inspect( obj, *, help=False, # 显示完整帮助文本(否则只显示第一段) methods=False, # 是否显示方法(callable 属性) docs=True, # 是否显示属性/方法的文档字符串 private=False, # 是否显示单下划线私有属性(以 "_" 开头) dunder=False, # 是否显示双下划线 dunder 属性(以 "__" 开头) sort=True, # 属性是否按字母序排序 all=False, # 一次性显示全部(methods + private + dunder) value=True, # 是否显示对象的值/repr )

其中all=True在源码中等价于同时开启methodsprivatedunder三个开关:

if all: methods = True private = True dunder = True

渲染细节与实现原理

从源码(marimo/_plugins/stateless/inspect.py)可以看到丰富的渲染逻辑:

  • 类型标签:根据对象类型着色——class(蓝)、function(绿)、method(紫)、module(橙)、instance(绯红)、其余为object(灰),并以"胶囊"样式显示在头部;
  • 标题:类/实例显示模块名.类名(如builtins.dict),函数/方法显示其名字;
  • 文档:默认只取 docstring 的第一段(以\n\n切分),help=True时显示全文;
  • 值展示:非类、非可调用对象会尝试用 marimo 的 HTML 序列化(as_html)渲染其值,失败则回退到repr(截断到 200 字符);
  • 函数签名:可调用对象显示完整签名,异步函数会标注async def
  • 属性表格:通过dir()收集属性后按过滤规则(private/dunder/methods)筛选,再逐行渲染。每个属性会智能分类为attributeproperty(斜体显示)、methoderror——访问属性抛异常时,会在表格中以红色错误信息展示该异常类型与消息,这对调试"属性访问报错"的场景非常有用(见_get_filtered_attributes_render_attribute_row的实现);
  • 方法行_format_method会拼接def 方法名(签名): 文档首行,文档超过 80 字符自动截断。

简言之,mo.inspect()相当于把 Python 标准库inspect的探查能力包装成了 marimo 原生的富文本输出组件,特别适合在探索性分析中快速"看穿"一个陌生对象。仓库中还提供了对应的冒烟测试用例 marimo/_smoke_tests/formatters/inspect_things.py 可作参考。


五、综合实战:编写"笔记本/脚本双兼容"代码

将上述 API 组合起来,可以写出这样一段既能在笔记本中交互运行、又能以python script.pymarimo run方式部署的代码:

import marimo as mo # 1. 环境感知:区分笔记本与会话式脚本 if mo.running_in_notebook(): print(">>> Notebook 模式") else: print(">>> Script 模式") # 2. 定位数据:本地与 WASM 双端通用 data_path = mo.notebook_location() / "data" / "dataset.csv" # 3. 单元格自省:在调试模式下打印依赖关系 if mo.running_in_notebook(): print("defs:", mo.defs()) print("refs:", mo.refs()) # 4. 用 mo.inspect 快速检视陌生对象 mo.inspect(data_path)

小结

  • mo.running_in_notebook():判断当前是否处于 marimo 笔记本 Kernel 上下文,底层通过get_context()+KernelRuntimeContext类型检查实现(marimo/_runtime/context/utils.py);
  • mo.defs()/mo.refs():返回当前单元格的定义名与引用名(已过滤未遮蔽的内置函数),基于运行时执行图,便于自省与调试(marimo/_runtime/runtime.py);
  • mo.notebook_dir():返回笔记本所在目录,脚本环境下回退为当前工作目录;
  • mo.notebook_location():非 WASM 下等同notebook_dir(),WASM 下返回网页 URL,是"本地 + 静态托管"双端数据加载的钥匙(marimo/_runtime/runtime.py);
  • mo.inspect():富文本对象检视器,支持methods/private/dunder/all/docs/sort/value等参数,属性访问异常会以红色错误行呈现(marimo/_plugins/stateless/inspect.py)。

这些 API 虽然不似 UI 控件那样显眼,却正是让 marimo 代码在不同运行环境(编辑、运行、脚本、测试、WASM)之间自由迁移的"粘合剂"。相关总览还可参考 docs/api/index.md,其他运行时 API(如mo.query_params()mo.cli_args()mo.app_meta())见 docs/api/query_params.md 与 docs/api/cli_args.md。

【免费下载链接】marimoA reactive notebook for Python — run reproducible experiments, query with SQL, execute as a script, deploy as an app, and version with git. Stored as pure Python. All in a modern, AI-native editor.项目地址: https://gitcode.com/GitHub_Trending/ma/marimo

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

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

立即咨询