Skip to main content

iceberg-loader

PyPI - Version PyPI - Python Version PyPI - Downloads CI License: MIT

📚 Documentation

iceberg-loader wraps PyIceberg to load data into Apache Iceberg tables. It uses PyArrow and handles mixed JSON fields, schema evolution, idempotent replacement, upserts, batching, and streaming.

Status: Actively developed and under testing. Tested against Hive Metastore and REST Catalog (Tabular, Polaris, self-hosted).

Why iceberg-loader?

  • Mixed JSON fields: converts dict and list values to strings before writing, including fields with mixed types.
  • Schema evolution: adds columns when enabled and preserves field IDs.
  • Write modes: append, overwrite, idempotent replacement via replace_filter, and upsert.
  • Streaming: commit intervals, batches, and IPC streams.
  • Configuration: LoaderConfig sets defaults that can be overridden per call.

Install

pip install "iceberg-loader[all]"

Or with uv:

uv add "iceberg-loader[all]"

Quickstart

Hive Metastore

from pyiceberg.catalog import load_catalog
from iceberg_loader import LoaderConfig, load_data_to_iceberg
from iceberg_loader.utils.arrow import create_arrow_table_from_data

catalog = load_catalog("default")
table_id = ("default", "comparison_complex_json")

data = [
    {"id": 1, "complex_field": {"a": 1, "b": "nested"}, "signup_date": "2023-01-01"},
    {"id": 2, "complex_field": {"a": 2, "b": "another", "c": [1, 2]}, "signup_date": "2023-01-02"},
    {"id": 3, "complex_field": [1, 2, 3], "signup_date": "2023-01-02"},
]

arrow_table = create_arrow_table_from_data(data)

config = LoaderConfig(write_mode="append", partition_col="day(signup_date)", schema_evolution=True)
load_data_to_iceberg(arrow_table, table_id, catalog, config=config)

REST Catalog

from iceberg_loader import LoaderConfig, get_rest_catalog, load_data_to_iceberg
from iceberg_loader.utils.arrow import create_arrow_table_from_data

catalog = get_rest_catalog(
    uri="https://api.tabular.io/ws",
    warehouse="s3://my-bucket/warehouse/",
    credential="your-oauth2-credential",
)
table_id = ("default", "my_table")

data = [
    {"id": 1, "name": "Alice", "signup_date": "2023-01-01"},
    {"id": 2, "name": "Bob", "signup_date": "2023-01-02"},
]

arrow_table = create_arrow_table_from_data(data)

config = LoaderConfig(write_mode="append", partition_col="day(signup_date)", schema_evolution=True)
load_data_to_iceberg(arrow_table, table_id, catalog, config=config)

Or use pyiceberg.yaml to configure your REST catalog and load it by name:

# ~/.pyiceberg.yaml (see examples/pyiceberg.yaml.sample for a full annotated example)
catalog:
  my-rest-catalog:
    type: rest
    uri: https://your-catalog-server.com/api
    warehouse: s3://my-bucket/warehouse/
    credential: your-oauth2-credential
    s3.endpoint: https://s3.amazonaws.com
    s3.region: us-east-1
from pyiceberg.catalog import load_catalog

catalog = load_catalog("my-rest-catalog")
# ... rest is identical to above

Which function to use?

Function Use when... Input Format
load_data_to_iceberg You have a single pa.Table in memory. pyarrow.Table
load_batches_to_iceberg You have a generator/iterator of batches (memory efficient). Iterator of pyarrow.RecordBatch
load_ipc_stream_to_iceberg You are reading from an Arrow IPC stream file/socket. File-like object or path

Preparing Data

These helpers convert Python dictionaries to Arrow data, including mixed fields:

from iceberg_loader.utils.arrow import create_arrow_table_from_data, create_record_batches_from_dicts

# 1. Convert list of dicts -> pa.Table
arrow_table = create_arrow_table_from_data(data_list)

# 2. Convert iterator of dicts -> Iterator[pa.RecordBatch]
batches = create_record_batches_from_dicts(data_generator(), batch_size=10000)

Alternatively, use standard PyArrow conversion: pa.Table.from_pylist(data).

The helpers serialize dicts and lists as JSON and convert other non-null values to strings too. For example, an integer id becomes an Arrow string. If you need to preserve scalar types, prepare a typed Arrow table with PyArrow instead.

For timestamp columns, prefer partition transforms such as day(ts) or hour(ts), especially when using load_timestamp.

Public API & Stability

  • Top-level exports include LoaderConfig, IcebergLoader, load_data_to_iceberg, load_batches_to_iceberg, load_ipc_stream_to_iceberg, get_rest_catalog, and expire_snapshots.
  • Data conversion helpers are available from iceberg_loader.utils.arrow. Pass loading options via LoaderConfig.
  • Avoid legacy positional arguments—use the config parameter only.
  • LoaderConfig validates partition expressions and rejects unsafe combos (e.g., replace_filter with upsert, identity partition on _load_dttm).

How we version

  • Semantic Versioning starting at 0.1.x: MINOR for compatible features, PATCH for fixes, MAJOR for breaking API changes.
  • Breaking changes to documented APIs are noted in RELEASE.md.

Release checklist

  • Bump version in pyproject.toml and src/iceberg_loader/__about__.py (they must match).
  • Update RELEASE.md with highlights and breaking notes.
  • Run uv lock, commit uv.lock if it changes, then verify it with uv lock --locked.
  • Run uv run ruff check ., uv run ty check, and uv run python -m pytest.
  • Tag and push (git tag -a vX.Y.Z ...), then let CI publish.

Contributing

See CONTRIBUTING.md for setup, coding style, and PR guidelines.

uv run ruff check . && uv run ruff format --check . && uv run ty check
uv run pytest

Contributors

Made with contrib.rocks.

License

iceberg-loader is distributed under the terms of the MIT license.

Metadata

Release files for iceberg-loader 0.1.4

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

Source distribution (sdist)

Source distribution for iceberg-loader 0.1.4
File Size Uploaded
iceberg_loader-0.1.4.tar.gz 19.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for iceberg-loader 0.1.4
File Interpreter ABI Platform
iceberg_loader-0.1.4-py3-none-any.whl Python 3 none any Details

Total release size: 43.8 kB

Release files / iceberg_loader-0.1.4.tar.gz

Download URL iceberg_loader-0.1.4.tar.gz
Size 19.2 kB
Tags Source
SHA-256 checksum
How to use checksums
518898811309df574152f63511d3a348fbcdc362ea43696a126b90c19774dac4
BLAKE2b-256 checksum
How to use checksums
9b67d4fb521bd1c475b92de7d5b7c3385e9f0a52a3e9a618f48daca4bd43009c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.8

Release files / iceberg_loader-0.1.4-py3-none-any.whl

Download URL iceberg_loader-0.1.4-py3-none-any.whl
Size 24.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e16257662799b01fbbea0cc4c6a70926b74bf48211b78869b990639fe6cda351
BLAKE2b-256 checksum
How to use checksums
004612d9ebf7f4759e15918c4facec91850c2faf5cede3bfbc16a8c4dd22812d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.8

Release history Release notifications | RSS feed

This release

0.1.4 This release

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

0.0.7

2 release files

0.0.6

2 release files

0.0.5

2 release files

0.0.4

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