babeldb para Python
Binding nativo e embarcado do babeldb, no estilo de sqlite3, lmdb, polars ou lancedb: o
banco roda dentro do processo Python, sem servidor. Por baixo é a receita da seção "Usar em outro
projeto (Rust)" do README principal: fjall + WAL write-through (Db::open_fjall_wal), escritas
por um group committer, leituras direto no banco. Módulo nativo babeldb._native (PyO3, abi3),
pacote Python babeldb com tipos (py.typed + .pyi).
Instalação
A partir do wheel já construído
pip install babeldb
O wheel é abi3: o mesmo arquivo serve para CPython 3.8 ou mais novo (Windows x64).
Construir o wheel
Requisitos: Rust (o rust-toolchain.toml da raiz fixa a versão; o rustup a instala sozinho),
Python 3.8+ e maturin. De dentro de bindings/python:
python -m venv .venv
.venv\Scripts\python -m pip install maturin pytest
.venv\Scripts\maturin build --release -i .venv\Scripts\python.exe
.venv\Scripts\python -m pip install --force-reinstall target\wheels\babeldb-0.1.1-cp38-abi3-win_amd64.whl
O wheel sai em target\wheels\. Para desenvolver, .venv\Scripts\maturin develop --release
compila e instala direto no venv.
Exemplo rápido
import babeldb
with babeldb.open("dados/app") as db: # cria o diretório se não existir
rev = db.put("usuario:1", b'{"nome": "Ana"}') # durável quando retorna
db.get("usuario:1") # b'{"nome": "Ana"}'
db.put("usuario:1", b'{"nome": "Bia"}', if_revision=rev) # compare-and-set
db.put("usuario:2", "x", if_absent=True) # só cria se não existir
db.scan("usuario:") # [(b'usuario:1', ...), (b'usuario:2', b'x')]
db.keys("usuario:", reverse=True, limit=1) # [b'usuario:2']
db.batch([("put", "a", "1"), ("delete", "usuario:2")]) # atômico, um commit
db.delete("a") # True
# Chat: chave = canal ‖ id da mensagem (big-endian), mensagens de um canal em ordem.
canal = 42
db.put(babeldb.message_key(canal, 1001), "oi")
ultimas = db.scan(babeldb.channel_prefix(canal), reverse=True, limit=50)
canal, msg_id = babeldb.parse_message_key(ultimas[0][0])
Referência da API
Chaves e valores aceitam bytes, bytearray, memoryview ou str (str vira UTF-8); valores
voltam sempre como bytes. Chave: 1 a 4096 bytes. help(babeldb.Db) mostra a mesma referência.
| Chamada | Retorno | O que faz |
|---|---|---|
babeldb.open(path, durability="immediate") |
Db |
Abre (ou cria) o banco no diretório path. babeldb.Db(path, durability=...) é o mesmo. |
db.put(key, value, *, if_absent=False, if_revision=None) |
int |
Grava; devolve a nova revisão. if_absent=True: só se a chave não existir. if_revision=r: só se a revisão atual for r (compare-and-set). Expectativa falhou: ConflictError. |
db.get(key) |
bytes | None |
Valor atual, ou None. |
db.delete(key, *, if_revision=None) |
bool |
Apaga; False se a chave não existia. Com if_revision=r, ConflictError se a revisão atual não for r (inclusive chave inexistente). |
db.scan(prefix=None, *, start=None, end=None, reverse=False, limit=0) |
list[tuple[bytes, bytes]] |
Registros em ordem de bytes da chave. prefix: chaves que começam com ele. start inclusivo, end exclusivo; prefix não combina com start/end. reverse=True: decrescente. limit=0: sem limite (com reverse, os últimos N). |
db.keys(...) |
list[bytes] |
Os mesmos argumentos de scan, só as chaves. |
db.batch(ops) |
list[int | None] |
ops: iterável de ("put", k, v) / ("delete", k). Atômico e durável; ver abaixo. |
db.sync() |
None |
Espera tudo o que foi confirmado antes ficar durável (modo buffered; no immediate já está). |
db.close() |
None |
Espera as chamadas em andamento, torna tudo durável e libera o diretório. Idempotente. |
db.closed, db.path, db.durability |
Propriedades só de leitura. | |
with babeldb.open(p) as db: |
Fecha ao sair do bloco (também com exceção). | |
babeldb.message_key(channel, message_id) |
bytes |
16 bytes: channel (u64 big-endian) ‖ message_id (u64 big-endian). |
babeldb.parse_message_key(key) |
tuple[int, int] | None |
Inverso de message_key; None se a chave não tiver 16 bytes. |
babeldb.channel_prefix(channel) |
bytes |
Os 8 bytes iniciais das chaves do canal (para scan). |
Revisões: um int (u64) que cresce a cada escrita do banco (não por chave). Guarde a de
put para usar em if_revision.
batch (tudo ou nada): as operações são aplicadas em ordem (uma operação vê o efeito das
anteriores na mesma chave) num único commit atômico e durável (Db::write_batch do núcleo). Se
qualquer operação for malformada ou inválida (por exemplo, chave vazia), nada é escrito e o erro
sobe. Retorno por operação: put → nova revisão; delete → revisão do registro apagado, ou
None se a chave não existia. As operações do batch não têm condições (último escritor vence) e
o batch é durável ao retornar nos dois modos de durabilidade. (O primitivo do group commit,
write_batch_each, aplicaria as operações válidas e pularia as inválidas; por isso batch não
usa ele.)
Exceções (todas derivam de babeldb.BabelError):
| Exceção | Quando |
|---|---|
ConflictError |
if_absent=True com a chave existente; if_revision diferente da revisão atual. Nada foi escrito. |
ClosedError |
Qualquer método (exceto close) depois de close(), e with num Db fechado. |
InvalidArgumentError |
Chave vazia ou com mais de 4096 bytes; valor grande demais; durability desconhecida; prefix junto com start/end; limit negativo; if_absent junto com if_revision; operação de batch malformada. |
BabelError |
Erros de E/S e do armazenamento; abrir um diretório que já está aberto neste processo. |
Tipos errados de chave/valor levantam TypeError; inteiros fora de u64 (revisões, helpers),
OverflowError.
Modos de durabilidade
"immediate"(padrão):put,deleteebatchsão duráveis quando a chamada retorna. Escritas simultâneas de várias threads entram no mesmo commit (group commit): N threads pagam uma escrita no WAL, não N."buffered":putedeleteretornam quando a escrita está commitada e visível (leituras já a veem), mas ainda não durável. Ela fica durável em até ~100 ms, antes de 64 MiB pendentes, emsync()e emclose()(WriteDurability::Buffered { flush_interval: 100 ms, max_pending_bytes: 64 MiB }). Num crash (queda de energia, processo morto) podem se perder as escritas confirmadas nos últimos ~100 ms.batchcontinua durável ao retornar.
O WAL grava em modo write-through (FILE_FLAG_WRITE_THROUGH): a garantia padrão do PostgreSQL no
Windows (ver docs/ e o módulo store::wal do núcleo). Ao sair do interpretador, os bancos ainda
abertos são fechados (atexit), o que torna durável o que estiver pendente; um processo morto à
força não passa por isso.
Threads
- Um
Dbpode ser usado por muitas threads ao mesmo tempo: compartilhe a mesma instância. - Toda chamada ao banco roda sem o GIL (
py.detach, o antigoallow_threadsdo PyO3): leituras rodam em paralelo e as escritas de threads diferentes compartilham commits. - Um
Dbpor diretório por processo: abrir de novo um diretório já aberto no mesmo processo levantaBabelError("already open") na hora, sem travar. Outro processo que abra o mesmo diretório recebe o erro da trava do fjall. close()espera as chamadas em andamento terminarem; as chamadas seguintes levantamClosedError. UmDbcoletado pelo garbage collector semclose()é fechado ao ser destruído.- Com
asyncio, as chamadas bloqueiam: useawait asyncio.to_thread(db.get, chave).
Limites
- Testado só no Windows 11 x64 com CPython 3.12. O wheel é abi3 (CPython 3.8+), mas as outras versões não foram testadas; Linux e macOS ainda não foram compilados.
- Chave de 1 a 4096 bytes. Chaves e valores são copiados a cada chamada: valores enormes custam memória (o limite do núcleo é 4 GiB por valor).
scanekeysdevolvem a lista inteira (sem cursor): pagine comstart/end+limit.- Transações: só
if_absent/if_revision(por operação) ebatch(atômico, sem condições). - Configuração fixa:
Config::adaptive()+WalConfig::default(). O banco ocupa o diretóriopathe o WAL é o arquivo<path>.walao lado dele (pré-alocado, 16 MiB). - PyPy e o Python sem GIL (3.13t) não são suportados.
Testes
De dentro de bindings/python, com o wheel instalado no venv (ver "Construir o wheel"):
.venv\Scripts\python -m pytest -q
O pytest roda contra o pacote instalado: o código-fonte fica em python/babeldb, fora do
sys.path, então import babeldb carrega o wheel.
Benchmark
.venv\Scripts\python bench.py # durability="immediate"
.venv\Scripts\python bench.py --durability buffered
Imprime puts/s e gets/s com valores de 512 B (aleatórios, incompressíveis), 1 e 8 threads.
Medido nesta máquina de desenvolvimento (Windows 11, NVMe; CPython 3.12, wheel --release),
20 000 operações por fase, um banco novo por fase:
| durability | threads | puts/s | gets/s |
|---|---|---|---|
immediate |
1 | 8 472 | 320 000 |
immediate |
8 | 34 834 | 129 870 |
buffered |
1 | 29 452 | 299 472 |
buffered |
8 | 113 013 | 151 644 |
Com 8 threads as escritas ganham com o group commit (várias escritas por commit). As leituras
com 8 threads rendem menos que com 1: cada get leva poucos microssegundos e o laço do benchmark
roda em Python, então a troca do GIL entre as threads (que toda chamada solta) custa mais do que
o paralelismo ganha. Leituras paralelas compensam quando cada chamada faz mais trabalho (valores
grandes, scan).
Metadata
Release files for babeldb 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| babeldb-0.1.1.tar.gz | 758.1 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| babeldb-0.1.1-cp38-abi3-win_amd64.whl | CPython 3.8 | abi3 | Windows x86-64 | Details |
| babeldb-0.1.1-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | CPython 3.8 | abi3 | Linux glibc 2.17+ x86-64 | Details |
| babeldb-0.1.1-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | CPython 3.8 | abi3 | Linux glibc 2.17+ ARM64 | Details |
| babeldb-0.1.1-cp38-abi3-macosx_11_0_arm64.whl | CPython 3.8 | abi3 | macOS 11.0+ ARM64 | Details |
| babeldb-0.1.1-cp38-abi3-macosx_10_12_x86_64.whl | CPython 3.8 | abi3 | macOS 10.12+ x86-64 | Details |
Total release size: 23.9 MB
Release files / babeldb-0.1.1.tar.gz
| Download URL | babeldb-0.1.1.tar.gz |
|---|---|
| Size | 758.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8b9bd31f2b1f9a2cd2af544085291c5b3ebeeb73a9475b97767440c2bcaba094
|
|
BLAKE2b-256 checksum How to use checksums |
3020d446d38685e47b616b5be5538262b817f00faea05e28abda5c067b887baf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.
Transparency logRelease files / babeldb-0.1.1-cp38-abi3-win_amd64.whl
| Download URL | babeldb-0.1.1-cp38-abi3-win_amd64.whl |
|---|---|
| Size | 1.3 MB |
| Tags | CPython 3.8 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
056f5348d4007ed4e80c2c5aabb7528ea27e3fc66d89bd9ce57a1dfefd43fef3
|
|
BLAKE2b-256 checksum How to use checksums |
ed948f21782532537b197d43c0e99aab6c4ca274f71a5543ff3515d482375e59
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.
Transparency logRelease files / babeldb-0.1.1-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | babeldb-0.1.1-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 9.8 MB |
| Tags | CPython 3.8 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
59fd8e8fb5269015f71bd42f4e8ca3c3109deb602901789f786ab11566df6810
|
|
BLAKE2b-256 checksum How to use checksums |
dd097765c7bc91a0bbbd6972420c15e641e4eb838d2d3fa7b30d6e0c21758cde
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.
Transparency logRelease files / babeldb-0.1.1-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | babeldb-0.1.1-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 9.0 MB |
| Tags | CPython 3.8 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
92c9395de0d2b2dfdd6cbe68f290ae92f300062c07ece5e1149700b698b7086a
|
|
BLAKE2b-256 checksum How to use checksums |
53044f325624ade09132d53f9e65c00faa86b50c5a0b4894b146a03ec5fbd9cd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.
Transparency logRelease files / babeldb-0.1.1-cp38-abi3-macosx_11_0_arm64.whl
| Download URL | babeldb-0.1.1-cp38-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 1.5 MB |
| Tags | CPython 3.8 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
f33b6542553a0aac96c9738f3b12eba83ad64e1932b167d6ba32473a280165c0
|
|
BLAKE2b-256 checksum How to use checksums |
0172161d2b259213d9654cbe339ccb29632cd81f7751534b0af452a953835372
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.
Transparency logRelease files / babeldb-0.1.1-cp38-abi3-macosx_10_12_x86_64.whl
| Download URL | babeldb-0.1.1-cp38-abi3-macosx_10_12_x86_64.whl |
|---|---|
| Size | 1.6 MB |
| Tags | CPython 3.8 abi3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
dcf209bc617b0715d7aac88b5c01def1f09b7213e633451fe113339e567eef81
|
|
BLAKE2b-256 checksum How to use checksums |
9e91902d642f48d7bd8d75cbd6bedf91262c8284ada011767ca865731f03ea29
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.
Transparency log