Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

SqlFileSystem v2 Python SDK

状态:活跃维护。 Python 是当前唯一开发、测试和发布的 SDK,将先在多个真实项目 中验证稳定性,再作为未来 Kotlin/Node.js SDK 的行为基准。

SDK 通过私有 ctypes 层调用 sfs-ffi ABI v2,同时提供同步 Sfs 和 asyncio AsyncSfs。低层 C 结构、raw handle、伪流式接口及尚未完成验收的后端不会进入稳定 公共 API。

安装

PyPI 分发名为 sfs-v2(代码仍 import sfs)。与 PyPI 已有的其他项目 sfs 不同,勿同时安装二者。每个平台的 wheel 仅内嵌该平台的原生库,由 pip 自动选择:

pip install sfs-v2==0.0.1.dev1

首次发布仅提供 Windows x86_64 与 Linux x86_64;不要将只包含某平台原生库的 wheel 标记为 py3-none-any。Linux wheel 的 manylinux/glibc 最低要求以实际发布文件名为准。

源码开发时先构建 FFI,并让 SFS_NATIVE_PATH 指向产物:

cargo build --release -p sfs-ffi

# Linux/macOS
export SFS_NATIVE_PATH=../../target/release/libsfs_ffi.so

# Windows PowerShell
$env:SFS_NATIVE_PATH="..\..\target\release\sfs_ffi.dll"

加载时 SDK 会执行 ABI 版本和全部 C 结构尺寸握手;Python 包与动态库不匹配时会在 open 前明确报错,而不是继续错误解释内存。

同步 API

from sfs import Sfs, WriteItem

with Sfs.open_sqlite("/path/to/db") as store:
    store.makedirs("/pages/2026")
    store.write_text("/pages/2026/a.html", "<html>...</html>")
    print(store.read_text("/pages/2026/a.html"))

    store.write_many([
        WriteItem("/pages/2026/b.html", b"..."),
        WriteItem("/pages/2026/c.html", b"..."),
    ])

Sfs 会为每次操作取得生命周期 lease;close() 会阻止新操作并等待所有在途调用 结束,随后只释放一次原生 handle。close 后调用任何方法都会抛 SfsClosedError。

OpenOptions(readonly=True) 会以只读方式挂载已有字典用于解码,不训练或改写字典。 所需字典缺失/损坏时读取必须明确报错,不会把压缩 payload 当成文件内容返回。

asyncio API

from sfs import AsyncOptions, AsyncSfs

store = await AsyncSfs.open_sqlite(
    "/path/to/db",
    async_options=AsyncOptions(
        queue_capacity=256,
        max_queued_bytes=256 * 1024 * 1024,
        write_batch_size=100,
        flush_interval=0.05,
    ),
)

async with store:
    await store.write("/result.bin", payload)

AsyncSfs 使用一个专用单线程 executor、有界队列、字节水位和单 writer 自动聚合并发 写请求。以下是稳定契约:

  • await write/write_many 正常返回,表示底层同步批量写已经成功提交;
  • 仅进入 asyncio Queue 不会完成 Future;
  • 同批失败会传播给该批全部等待者;
  • aclose() 停止接收新任务、排空队列、等待原生调用,再关闭 handle;
  • 调用方取消等待、远程断线或提交 ACK 丢失时底层写可能仍已完成;这些情况的 outcome unknown,不表示“未写入”。只有 await 正常返回才是 commit 成功 ACK。

分页与扫描

普通列表默认最多返回 1000 条;大目录优先使用惰性 iterator:

for info in store.iter_files("/pages", page_size=1000):
    print(info.full_path)

扫描默认遇错中止,避免静默漏文件:

from sfs import ScanFilter, ScanOptions

with store.scan(ScanOptions(filter=ScanFilter(extensions=("html",)))) as scan:
    for item in scan:
        process(item.info, item.data)

asyncio 版本返回可显式关闭的 AsyncSfsScan,可读取最终统计和 Collect 错误:

scan = store.scan(ScanOptions(filter=ScanFilter(extensions=("html",))))
async with scan:
    async for item in scan:
        await process(item)
stats = await scan.stats()
errors = await scan.take_errors()

SDK 不提供 scan.to_list(),防止把大规模扫描结果全部装入内存。扫描事件携带完整 内容,因此单文件硬上限为 4 MiB;更大文件应改走分块读取。同步 SfsScan 与异步 AsyncSfsScan 都应显式使用 context manager;store close 也会等待仍活动的异步扫描 句柄关闭后再终止 executor。

错误

所有错误继承 SfsError,并携带稳定字段:

try:
    store.read("/missing")
except SfsError as error:
    print(error.code, error.operation, error.path, error.database_code, error.retryable)

常用子类包括 SfsNotFoundError、SfsDatabaseLockedError、 SfsCorruptDataError、SfsReadonlyError 和 SfsResourceExhaustedError。

维护与实验能力

空间回收不与常规读写平级:

report = store.maintenance.shrink()
if not report.succeeded:
    print(report.vacuum_failed_volumes)

SDK 优先使用 optional sfs_shrink_v2 获取并释放 vacuum_failed_volumes;早期 ABI v2 缺少新符号时会回退 legacy 24-byte 报告,失败卷只能显示为空。需要完整维护诊断时应 使用当前 native。

PostgreSQL、MySQL 和远程 gRPC 入口尚未完成 Python 集成矩阵,只能显式从 sfs.experimental 导入,不属于当前兼容承诺。当前稳定支持范围仍是 SQLite; Kotlin/Node.js SDK 继续封存。

远程连接可匿名,也可传 opaque bearer token:

import os
from sfs.experimental import connect_remote

store = connect_remote(
    "http://127.0.0.1:50051",
    token=os.environ.get("SFS_TOKEN"),
)

调用方传不含 scheme 的 opaque token;Python 不改写、不记录它,gRPC 适配器自动构造 authorization: Bearer <token> header。远程句柄直接复用现有 Sfs.scan();底层 ScanV2 会传输 COLLECT 错误并要求唯一 final stats,无需新增 remote scan API。远程 scan 的最低 协议要求是服务端同样实现当前 ScanV2;连接旧服务端收到 gRPC Unimplemented 时会映射 为 SfsUnsupportedError,不会保真假成功地回退到缺少 COLLECT errors/final stats 的 legacy scan。当前没有 Python 公开 stream/per-call-deadline API,也没有用于自签/私有 CA 的 Python 参数; 实验性 connect_remote("https://your-host:51337", token=...) 的 HTTPS endpoint 可直通 底层 gRPC 客户端,使用操作系统信任根验证证书链和主机名,不禁用 TLS 验证。此能力 尚不属于稳定远程 SDK API,私有/自签 CA 目前只能通过 Rust GrpcClient::connect_with_auth_and_ca(endpoint, token, Some(ca_pem)) 显式配置。异步爬虫可用 async with await sfs.experimental.connect_remote_async(endpoint, token) as store:,其连接/读写在 专用单线程 executor 中执行,成功 await store.write(...) 才代表服务端写入已提交。 Rust 客户端为普通 unary RPC 设置默认 120 秒截止时间;爬虫进程可用环境变量 SFS_REMOTE_REQUEST_TIMEOUT_SECS=1..600 调整。超时的写入结果可能已经提交, 不能自动盲重试;流式传输尚无客户端完整/空闲截止时间。 SFS→PostgreSQL 是独立 TLS 链路:每个 SFS 进程的 PG DSN 指定 sslmode=require,驱动才强制 TLS、验证 CA 与服务器主机名;私有 CA 在 SFS 主机上用 SFS_PG_TLS_CA_FILE=/absolute/path/pg-ca.pem 指定(否则使用操作系统信任根),不要在爬虫进程设置 PG DSN 或分发数据库凭据。未指定 sslmode 或使用 prefer(SFS 的 prefer 不尝试 TLS)只有明确的数字回环 IP/Unix socket 才保留明文,远端/localhost 主机名将拒绝;可信隧道若确需明文须显式 sslmode=disable;sslmode=verify-full 和 sslrootcert 不是当前 tokio-postgres 可解析的 DSN 参数,SFS 的 require 明确执行更严格的完整证书/主机名验证;各业务/字典连接与异步连接池会固定打开时的 CA 信任配置,轮换 CA 后重启服务。直连 PG 的实验性 Python FFI 路径也遵守同一配置,但这不是推荐的多爬虫架构。 服务端内置 TLS 同时保护 HTTPS REST 与 gRPC(HTTP-only 模式也启用 HTTPS); 非 loopback 监听必须同时配置有效 bearer token 和 TLS PEM 证书/私钥,仅配置 token 不能使用明文监听。不得用 Python 示例经非 loopback 明文 HTTP 传 token。证书密钥文件 路径可通过 CLI --tls-cert / --tls-key(或环境变量 SFS_TLS_CERT / SFS_TLS_KEY)成对传递;token 建议从安全秘密管理器注入 SFS_AUTH_TOKEN,勿写在 日志/源码/命令行。

容量边界必须区分:远程普通 read/write 受 300 MiB unary message ceiling 约束;底层 C 真流 (SQLite 本地与 gRPC 远程)单 chunk 最大 4 MiB、单文件最大 8 GiB。C 写流只有显式 flush/finish 成功才拿到 durable commit ACK;未 flush 直接 close 会 abort。由于 Python 尚未公开 stream wrapper,8 GiB 不是当前 Python 普通 read/write 的承诺。

测试

python -m pytest test_open_options.py test_sfs.py test_async_sfs.py -v

Release files for sfs-v2 0.0.1.dev1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for sfs-v2 0.0.1.dev1
File Interpreter ABI Platform
sfs_v2-0.0.1.dev1-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
sfs_v2-0.0.1.dev1-py3-none-manylinux_2_28_x86_64.whl Python 3 none Linux glibc 2.28+ x86-64 Details

Total release size: 10.1 MB

Release files / sfs_v2-0.0.1.dev1-py3-none-win_amd64.whl

Download URL sfs_v2-0.0.1.dev1-py3-none-win_amd64.whl
Size 4.6 MB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
37f6a80a12ea8527555566b63eeb13711843dfa3a047b52406ebe75e0723a34f
BLAKE2b-256 checksum
How to use checksums
68b73b524e5213c235591bdbc4c0ea1aa07c0fc33f47d929a17b02e8f793fa92
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.9

Release files / sfs_v2-0.0.1.dev1-py3-none-manylinux_2_28_x86_64.whl

Download URL sfs_v2-0.0.1.dev1-py3-none-manylinux_2_28_x86_64.whl
Size 5.5 MB
Tags Linux glibc 2.28+ x86-64 Python 3
SHA-256 checksum
How to use checksums
e720b0a008ee834bfbf6263dee2ff60f02d6f38fabd4f1b1b1ce6507b1d9e05f
BLAKE2b-256 checksum
How to use checksums
ced37633f0c765f49338309660038ed56aa6a3b87120d4afb47713885baa6f62
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.9

Release history Release notifications | RSS feed

This release

0.0.1.dev1 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page