Files, blobs and Zarr arrays
Store files and Zarr arrays in the lakehouse from a notebook, under your own catalog grants.
Not everything is a table. From a notebook you can keep files of any kind — CSVs, PDFs, Parquet, images — and Zarr arrays in the lakehouse, next to your Iceberg tables and governed by the same catalog grants.
How it works
Files and arrays live in a generic table: a catalog entry in a namespace, like an Iceberg table,
that holds files instead of rows. Two helpers in databaas-utils open one for you:
| Helper | Returns |
|---|---|
get_store(namespace=...) | A store for reading and writing files under a generic table |
get_zarr_group(table, namespace=...) | A Zarr group for reading and writing arrays |
Both create the namespace and the generic table if they do not exist yet. The catalog signs every request on your behalf and checks your grants each time, so you never hold storage keys, and you can only read or write where you have been granted access. See data permissions.
Like an Iceberg table, a generic table is shared lakehouse data, not a private folder. Keep experiments in a namespace of your own.
Store and read files
from pathlib import Path
from databaas_utils.notebook import get_store
store = get_store(namespace="sandbox")
uri = store.put("reports", "2026/summary.csv", Path("summary.csv")) # -> "s3://…/summary.csv"
store.put("reports", "2026/notes.txt", Path("notes.txt"))
for obj in store.list("reports", prefix="2026"):
print(obj)
store.get("reports", "2026/notes.txt", Path("notes-downloaded.txt"))
store.delete("reports", "2026/notes.txt")Keys are relative to the generic table, so "2026/summary.csv" is a file inside sandbox.reports.
Only put creates the generic table on first use; get, list and delete never do, so a
misspelled table name fails instead of silently creating an empty one. store.open(table, key)
returns a readable file object without staging it to disk first, and store.uri(table, key) returns
the s3:// URI an object has or would have.
Pass the URI a put returns when you need to hand the file to something else, such as
dlt — not the bytes themselves.
Store and read Zarr arrays
import numpy as np
from databaas_utils.notebook import get_zarr_group
root = get_zarr_group("hello_zarr", namespace="sandbox") # created if missing
root["temperature"] = np.zeros((10, 10), dtype="f4")root = get_zarr_group("hello_zarr", namespace="sandbox", read_only=True)
list(root.array_keys())
root["temperature"][:2, :2]read_only and create choose how the group opens:
read_only | create | Mode | Behaviour |
|---|---|---|---|
True | ignored | r | Read only; the store must already exist |
False | True | a | Read and write; created if missing (default) |
False | False | r+ | Read and write; the store must already exist |
Every chunk you read or write is a separate signed request, so larger chunks and fewer reads are faster than many small ones.
Your token refreshes itself
get_store() and get_zarr_group() each resolve your identity on their own — there is no catalog
object to build or pass between them first. Like the Iceberg catalog, the token underneath refreshes
itself on every request, so a store or a Zarr root stays usable for as long as your notebook runs.
See your catalog does not go stale.
Find them in the Data Catalog
A generic table appears in the Data Catalog in its namespace, with a format badge and its own icon. It has no preview or schema, only its format, location and permissions — see table details. Grant access to it the same way as to a table.