marimo 杂项 API 完全指南:`running_in_notebook`、`defs`/`refs`、`notebook_dir` 与 `mo.inspect()` 的实战运用
marimo 杂项 API 完全指南running_in_notebook、defs/refs、notebook_dir与mo.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/marimomarimo 是一个以纯 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.pymddoc 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)其判定逻辑分为两步上下文是否初始化marimo 运行时会通过get_context()获取当前运行时上下文若抛出ContextNotInitializedError例如在普通 Python 解释器、pytest 或部分 CLI 场景下直接返回False上下文类型是否为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从中提取两类信息defsdefinitions当前单元格定义/赋值的名字refsreferences当前单元格引用、但定义在其他地方的名字。用法示例import marimo as mo # 在本单元格中定义 x 1 y x 1 # 查看当前单元格的 defs 与 refs print(mo.defs()) # (x, y) print(mo.refs()) # (x,) —— 取决于 x 是否在其它单元格中定义典型应用场景是自省式调试在一个单元格末尾打印出该单元格输出了哪些变量、依赖了哪些变量快速核对数据流关系。也可以配合条件逻辑根据本单元格是否定义某变量来决定后续分支。源码实现细节两个函数都定义在 marimo/_runtime/runtime.pymddoc 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的内置函数名即如果单元格引用了len、print等内置函数而图中又没有用户自定义的同名定义则这些名字不会出现在返回元组中避免噪音。值得注意的几个行为特征两者都返回排序后的元组保证多次调用结果稳定若上下文未初始化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(fFound 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 # 检视一个类methodsTrue 展开方法列表 mo.inspect(list, methodsTrue) # 检视一个实例 my_dict {key: value} mo.inspect(my_dict) # 显示全部属性包括私有_x与双下划线__x__成员 mo.inspect(my_dict, allTrue)在单元格中直接写下mo.inspect(...)作为单元格最后一个表达式即可看到渲染结果顶部是类型标签与对象名的头部带色彩区分下方依次是文档摘要、对象值/签名、以及按表格排布的属性列表。完整参数说明mo.inspect()是一个Html子类实现位于 marimo/_plugins/stateless/inspect.py构造签名如下mo.inspect( obj, *, helpFalse, # 显示完整帮助文本否则只显示第一段 methodsFalse, # 是否显示方法callable 属性 docsTrue, # 是否显示属性/方法的文档字符串 privateFalse, # 是否显示单下划线私有属性以 _ 开头 dunderFalse, # 是否显示双下划线 dunder 属性以 __ 开头 sortTrue, # 属性是否按字母序排序 allFalse, # 一次性显示全部methods private dunder valueTrue, # 是否显示对象的值/repr )其中allTrue在源码中等价于同时开启methods、private、dunder三个开关if all: methods True private True dunder True渲染细节与实现原理从源码marimo/_plugins/stateless/inspect.py可以看到丰富的渲染逻辑类型标签根据对象类型着色——class蓝、function绿、method紫、module橙、instance绯红、其余为object灰并以胶囊样式显示在头部标题类/实例显示模块名.类名如builtins.dict函数/方法显示其名字文档默认只取 docstring 的第一段以\n\n切分helpTrue时显示全文值展示非类、非可调用对象会尝试用 marimo 的 HTML 序列化as_html渲染其值失败则回退到repr截断到 200 字符函数签名可调用对象显示完整签名异步函数会标注async def属性表格通过dir()收集属性后按过滤规则private/dunder/methods筛选再逐行渲染。每个属性会智能分类为attribute、property斜体显示、method或error——访问属性抛异常时会在表格中以红色错误信息展示该异常类型与消息这对调试属性访问报错的场景非常有用见_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.py或marimo 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.pymo.defs()/mo.refs()返回当前单元格的定义名与引用名已过滤未遮蔽的内置函数基于运行时执行图便于自省与调试marimo/_runtime/runtime.pymo.notebook_dir()返回笔记本所在目录脚本环境下回退为当前工作目录mo.notebook_location()非 WASM 下等同notebook_dir()WASM 下返回网页 URL是本地 静态托管双端数据加载的钥匙marimo/_runtime/runtime.pymo.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),仅供参考