
marimo 远程存储实战用 obstore、fsspec 与 Hugging Face Hub 在编辑器内浏览对象存储【免费下载链接】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 通过自动识别笔记本中的 obstore、fsspec 与 huggingface_hub 连接对象将云端存储变为 Files 侧边栏中可浏览、可搜索、可下载的数据源。本篇完整覆盖文档中的连接建立方式UI 与代码两条路径、S3 endpoint 的常见坑点并结合源码深入讲解 marimo 的存储后端检测链路、协议归一化与签名 URL 下载机制帮助你在不离开编辑器的情况下打通云存储工作流。支持哪些存储库检测机制一览marimo 会自动发现auto-discover笔记本中满足特定类型条件的变量。支持的库与基类如下库基类示例存储obstoreobstore.store.ObjectStoreS3Store、GCSStore、AzureStore、HTTPStore、LocalStore、MemoryStorefsspecfsspec.AbstractFileSystemS3FileSystem、GithubFileSystem、FTPFileSystem、DatabricksFileSystem及更多内置实现huggingface_hubhuggingface_hub.HfApi浏览 Hugging Face Hub数据集、模型、空间、buckets从源码结构看这三类后端按固定优先级注册在 get_storage.py 中STORAGE_BACKENDS: list[type[StorageBackend[Any]]] [ Obstore, HuggingfaceApi, FsspecFilesystem, ]get_storage_backends_from_variables()遍历内核中所有(变量名, 值)对对每个变量依次调用各后端的is_compatible()进行isinstance判定obstore 判定为ObjectStore实例、fsspec 判定为AbstractFileSystem实例、Hugging Face 判定为HfApi实例命中第一个兼容后端即停止。因此一个变量只会归入一个命名空间且判定前会先通过DependencyManager确认对应库已安装未安装时直接跳过不会抛出导入错误。检测并非只在面板打开时进行每次单元格执行完毕后运行器会触发同步的 post-execution hookbroadcast_storage_backends见 hooks_post_execution.py把新发现的连接转换为StorageNamespace并通过StorageNamespacesNotification广播给前端。值得注意的是storage_backend_to_storage_namespace()在构造命名空间时刻意不拉取条目列表storage_entries[]——因为该 hook 在同步上下文中执行、可能阻塞内核条目列表由前端按需再取。创建存储连接marimo 支持两条建立连接的路径UI 或代码。通过 UI 创建在侧边栏 Files 面板中展开Remote Storage分区点击Add remote storage按钮UI 会引导你逐项填写连接信息。marimo 还会检测内核环境中的凭据并给出Quick add快捷建议集成检测依据Amazon S3设置了AWS_ACCESS_KEY_ID和AWS_SECRET_ACCESS_KEY或设置了AWS_PROFILES3 兼容存储同上并带有自定义 endpointAWS_ENDPOINT_URL或AWS_ENDPOINT_URL_S3例如 MinIO、Cloudflare R2更细的检测逻辑何时触发建议、如何解析环境变量参见 Detecting data sources from your environment 一节的说明。如果目标存储不在 UI 支持范围内可以直接用下面的代码方式连接。通过代码创建obstorefrom obstore.store import S3Store store S3Store.from_url( s3://my-bucket, access_key_id..., secret_access_key..., )S3 兼容存储还可以使用容器平台发放的凭据container-vended credentials认证——适用于 ECS/EKS 任务角色和 CoreWeave 沙箱等由平台注入凭据 endpoint 与 token 文件的场景import os from obstore.store import S3Store store S3Store( my-bucket, endpointhttps://my-bucket.cwobject.com, virtual_hosted_style_requestTrue, container_credentials_full_urios.environ[AWS_CONTAINER_CREDENTIALS_FULL_URI], container_authorization_token_fileos.environ[AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE], )S3 endpoint 常见坑点AWS_ENDPOINT_URL_S3的优先级高于endpoint参数一旦设置了该环境变量显式传入的 endpoint 会被静默忽略virtual_hosted_style_requestTrue要求 bucket 名已经在 endpoint 主机名内与 boto3 不同obstore 不会自动把 bucket 前缀拼到主机名前面。fsspecfrom fsspec.implementations.github import GithubFileSystem repo GithubFileSystem(orgmarimo-team, repomarimo)任何fsspec.AbstractFileSystem的子类都可以被识别因此 S3、GCS、Azure、FTP、Databricks、GitHub 等实现均适用。Hugging Face Hubfrom huggingface_hub import HfApi hf HfApi() # 可选: HfApi(tokenos.environ.get(HF_TOKEN))面板中找到的文件可以直接用hf://URL 在 Polars、pandas 或 DuckDB 中读取df pl.read_csv(hf://datasets/scikit-learn/Fish/Fish.csv)单元格执行后Remote Storage分区即会填充该连接、其检测到的协议protocol与根路径root path。多连接与命名空间隔离同一个笔记本中可以有多个存储连接每一个都作为独立的命名空间namespace呈现面板头部显示的是变量名用于区分不同连接from obstore.store import S3Store prod S3Store.from_url(s3://prod-bucket) staging S3Store.from_url(s3://staging-bucket)在实现上StorageNamespace定义于 models.py由五个关键字段构成name变量名即命名空间标识、display_name友好名称如 Amazon S3、Cloudflare R2、Coreweave、protocol归一化后的协议、root_path桶名或根路径内存存储为 None、backend_typefsspec/obstore/huggingface三选一。条目数据则由StorageEntry描述path、kindfile/directory/object、size、last_modified、metadata与推断出的mime_type前端正是靠 MIME 类型决定哪些文件可以预览。源码深潜marimo 如何理解一个存储连接协议归一化与厂商识别面板上显示的 Amazon S3 / Cloudflare R2 等标签来自 storage.py 中两层协议判定协议映射_PROTOCOL_MAP把各库的原始协议串归一到已知类型例如s3a→s3、gs→gcs、abfs/abfss/az/adl→azure、r2→cloudflare、memory→in-memoryendpoint URL 模式匹配detect_protocol_from_url()按有序的模式表_URL_PATTERNS扫描 endpoint第一个命中即返回。顺序很关键——Cloudflarecloudflare、r2.与 CoreWeavecwobject、cwlota、coreweave的厂商特征必须排在通用的s3/amazonaws之前检查否则 S3 兼容服务的 URL 会被误判为 AWS S3。obstore 后端的protocol属性会优先读store.config中的 endpoint 做 URL 识别失败时回退到具体 Store 类S3Store→s3、GCSStore→gcs等。这里还有一个防御性设计某些 obstore 版本对带allow_httpTrue的合法S3Store读取 config 时会直接 panic抛出继承自BaseException的PanicException因此_config用cached_property缓存结果并捕获BaseException确保每个存储至多 panic 一次。目录列表分页、虚拟目录与缓存失效三种后端统一实现list_entries(prefix, limit, page_token)接口默认分页大小DEFAULT_FETCH_LIMIT 100见 models.py。细节差异值得注意obstore调用list_with_delimiter(prefix)把 common prefixes如folder/映射为目录条目——此时拿不到大小与修改时间除非递归列出。源码注释明确指出对象存储的单次带分隔符列表通常上限约 1000 条而该实现不做超过一次 listing 的翻页因此条目极多的目录会被静默截断。此外还会跳过某些 S3 客户端创建的零字节目录标记对象foldersize 0。fsspec调用ls(path, detailTrue)针对 fsspec 的 dircache 陈旧缓存问题返回只含被查询路径自身的self-entry实现了检测 → 清除dircache中 root/parent/target 三个键 → 重试的自愈逻辑。同步的ls/open/info均被asyncio.to_thread包装避免阻塞事件循环。Hugging Face根列表并非对象存储语义而是聚合当前用户的 datasets、models、spaces各上限 50 条通过whoami()获取用户名未登录则回退为公开仓库与 buckets_parse_hub_path()负责把datasets/org/name/...、spaces/...、buckets/namespace/bucket、org/model这类 Hub 路径解析为仓库类型 仓库内路径下载走hf_hub_download范围读则临时借用HfFileSystemblock_size0以绕过 fsspec 的超前读缓存避免过度拉取。下载与签名 URL面板中的复制 URL / 下载文件背后是StorageBackend的download()、read_range()与sign_download_url()三个异步接口models.pyobstore 后端仅对S3Store、GCSStore、AzureStore生成签名 GET URL其余类型如HTTPStore返回 None默认有效期SIGNED_URL_EXPIRATION 60秒签名失败只记录日志、不中断交互fsspec 后端调用store.sign(path, expiration...)实现不支持签名NotImplementedError时同样静默降级Hugging Face 的 resolve URL 本身不设过期repo 文件直接用hf_hub_url()构造bucket 文件则按 huggingface_hub 内部相同的方式手工拼接{endpoint}/buckets/{id}/resolve/{path}。download_file()在download()之上统一从路径中提取文件名与扩展名无扩展名时归为bin供服务端生成下载响应。验证与延伸阅读存储后端的识别与行为在 tests/_data/_external_storage/ 下有对应测试test_get_storage.py覆盖变量到后端的映射逻辑test_huggingface.py覆盖 Hub 路径解析与列表行为test_storage_models.py覆盖命名空间/条目模型。若你的场景更偏向数据库而非文件存储可继续阅读 数据源自动检测 相关的文档章节核心实现文件集中在 marimo/_data/_external_storage/ 目录get_storage.py、storage.py、huggingface.py、models.py、utils.py是理解 Files 面板远程存储行为的最佳入口。【免费下载链接】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),仅供参考