Skip to main content

sas7bdat-polars

A Polars IO plugin for reading SAS7BDAT files, backed by the SIMD-accelerated sas7bdat Rust parser. It registers a native IO source via polars.io.plugins.register_io_source, so scans are lazy and support projection and predicate pushdown straight into the reader.

Installation

pip install sas7bdat-polars

To also get the standalone sas7bdat command (convert / info / head), install the extra:

pip install "sas7bdat-polars[cli]"

That pulls in sas7bdat-cli, a separate binary wheel built from the same parser. It is kept separate on purpose: it carries no polars pin and no Python floor, so CLI-only users do not inherit this package's constraints.

Version constraints

This wheel is tightly coupled to its build environment:

  • Polars is pinned to 1.41.*. The extension shares the Polars Rust ABI (via polars-ffi) with the in-process polars package, so the installed polars must match the version the wheel was built against. A mismatch is undefined behavior, not a graceful error.
  • Built against the CPython stable ABI (abi3, minimum 3.12), so a single cp312-abi3 wheel runs on CPython 3.12 and newer.

Usage

import polars as pl
import sas7bdat_polars as sp

# Eager read — the ergonomic default. ALWAYS pass `columns`: SAS7BDAT is wide and
# row-oriented, so projecting the columns you need is the biggest speed-up.
df = sp.read_sas("data.sas7bdat", columns=["name", "age"])
df = sp.read_sas("data.sas7bdat", columns=["age"], n_rows=1_000_000)   # bound I/O
df = sp.read_sas("data.sas7bdat", columns=["age"], predicate=pl.col("age") > 30)

# Lazy scan — returns a LazyFrame; filters/projections push down into the reader.
lf = sp.scan_sas("data.sas7bdat", columns=["name", "age"])
df = lf.filter(pl.col("age") > 30).collect()

# Header-only metadata (row/column count, encoding, size) without decoding the body.
info = sp.sas_info("data.sas7bdat")   # {'n_rows': ..., 'n_columns': ..., 'encoding': ...}

# Hydrate value labels from a companion catalog.
lf = sp.scan_sas("data.sas7bdat", catalog_path="formats.sas7bcat")

# Inspect the Arrow schema without reading rows.
schema = sp.schema_for_file("data.sas7bdat")

Performance & threading

Benchmarked on a 2.1 GB / 4041-column file (warm cache): a full .collect() takes ~1.8 s (decodes every column) while read_sas(columns=[one]) takes ~0.04 s. The rules:

  • Always project (read_sas(columns=...) / scan_sas(columns=...)). Reading one column instead of all is ~50× on wide files and the biggest lever by far.
  • Bound huge reads with n_rows= when you only need a peek — the reader's row limit stops after the first pages, cutting I/O.
  • Let the reader parallelise. It runs its own SIMD page decode across all cores; tune with set_scan_threads(n) (or SAS7BDAT_SCAN_THREADS). Do not throttle Polars' own pool (POLARS_MAX_THREADS) — it does not control the decoder and only starves the pipeline. (The library warns if it detects this mistake.)
  • Streaming works (.collect(engine="streaming")): the reader is Send + Sync.
sp.set_scan_threads(8)   # cap decode threads; set_scan_threads(0) resets to all cores
sp.scan_threads()        # -> effective count

# Return character columns as Categorical (low-cardinality category codes).
lf = sp.scan_sas("survey.sas7bdat", categorical=True)

# SAS stores every numeric column as a float. Declare integer-coded columns
# (registry/category codes) explicitly to get Int64 out instead of Float64:
lf = sp.scan_sas(
    "bef2020.sas7bdat",
    schema_overrides={"KOEN": pl.Int64, "SOCIO13": pl.Int64, "HFAUDD": pl.Int64},
)

categorical=True casts every character column to Categorical in the lazy plan (via Polars' own cast — equivalent to sp.scan_sas(path).with_columns(pl.col(pl.String).cast(pl.Categorical))). The benefit is downstream: group-by / join / sort on these columns run on u32 codes and are ~10–15× faster. It is not a read or memory win — Polars' String is already compact, so casting adds a little to the read (~0.6s on a 2.5k-string- column file) and uses more memory; only enable it when you'll group/join on the string columns. (Contrast with the R binding's categorical=TRUE, where factor is a read-speed and memory win.)

schema_overrides is applied at schema time, so the lazy schema and the collected frame always agree, and the same override map yields the same dtypes for every file of a register. Override names that don't exist in a given file are ignored, so a register-wide map can be passed wholesale. If a file contains a value that violates an Int64 override (non-integral or out of range), the scan fails with an error naming the column, row, and value — it never silently falls back to Float64. Supported override dtypes: Int64, Float64, Date, Datetime, Time, String, Binary (numeric columns can only be re-typed to numeric/temporal dtypes, character columns to String/Binary). Feature-detect with sp.PLUGIN_CONTRACT_VERSION >= "sas7bdat_polars.v2".

License

MIT — see the repository for details.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

sas7bdat_polars-0.9.0-cp312-abi3-win_amd64.whl (5.3 MB view details)

Uploaded CPython 3.12+Windows x86-64

sas7bdat_polars-0.9.0-cp312-abi3-manylinux_2_28_x86_64.whl (5.9 MB view details)

Uploaded CPython 3.12+manylinux: glibc 2.28+ x86-64

sas7bdat_polars-0.9.0-cp312-abi3-manylinux_2_28_aarch64.whl (5.3 MB view details)

Uploaded CPython 3.12+manylinux: glibc 2.28+ ARM64

sas7bdat_polars-0.9.0-cp312-abi3-macosx_11_0_arm64.whl (4.8 MB view details)

Uploaded CPython 3.12+macOS 11.0+ ARM64

File details

Details for the file sas7bdat_polars-0.9.0-cp312-abi3-win_amd64.whl.

File metadata

  • Download URL: sas7bdat_polars-0.9.0-cp312-abi3-win_amd64.whl
  • Upload date:
  • Size: 5.3 MB
  • Tags: CPython 3.12+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for sas7bdat_polars-0.9.0-cp312-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 dbf839ed12a43bc06d593b2127f90f5cb214d6dfbdf6af81e6cf07f413f4c869
MD5 41d0b3666ab6b815151927b392da2c64
BLAKE2b-256 0e000ba714cf833b9ef92781e0b5d521852e59b7b8578a195f2d1b12929e04fe

See more details on using hashes here.

File details

Details for the file sas7bdat_polars-0.9.0-cp312-abi3-manylinux_2_28_x86_64.whl.

File metadata

  • Download URL: sas7bdat_polars-0.9.0-cp312-abi3-manylinux_2_28_x86_64.whl
  • Upload date:
  • Size: 5.9 MB
  • Tags: CPython 3.12+, manylinux: glibc 2.28+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for sas7bdat_polars-0.9.0-cp312-abi3-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 9391e2678859120f468af34b95164402fd35b1477f2cece826340a1b4bc52afd
MD5 23e7353342e2a4b09919e89b9a2d62bd
BLAKE2b-256 2d45313871a503c2760af2857a8340e9077b5e520f240634b03a9dbf9143c384

See more details on using hashes here.

File details

Details for the file sas7bdat_polars-0.9.0-cp312-abi3-manylinux_2_28_aarch64.whl.

File metadata

  • Download URL: sas7bdat_polars-0.9.0-cp312-abi3-manylinux_2_28_aarch64.whl
  • Upload date:
  • Size: 5.3 MB
  • Tags: CPython 3.12+, manylinux: glibc 2.28+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for sas7bdat_polars-0.9.0-cp312-abi3-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 9bf4f34c24726493079865c63c6ccd111d9e7c4948927e08f324f2af543adc0c
MD5 a11b0ad83a01d3dec50dfb8826acf07f
BLAKE2b-256 ecf96949b0f8b61649dcaa1da091b608fdb9e4d8ca7601ba60c7f21e218fc5a6

See more details on using hashes here.

File details

Details for the file sas7bdat_polars-0.9.0-cp312-abi3-macosx_11_0_arm64.whl.

File metadata

  • Download URL: sas7bdat_polars-0.9.0-cp312-abi3-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 4.8 MB
  • Tags: CPython 3.12+, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for sas7bdat_polars-0.9.0-cp312-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 aadca3ed539bb7a5eafcd78e40a4c1e063d7fd23e7b05db422f3f1ef3f8408fa
MD5 27fce78e476c5fbb42e847d998f77041
BLAKE2b-256 da585ecbe2842210a18dff59a3aac5ce4f06ce193e768c1ce185bde1d726b7c4

See more details on using hashes here.

Release history Release notifications | RSS feed

0.10.0

4 files

0.9.2

4 files

0.9.1

4 files

This release

0.9.0 This release

4 files

0.8.0

4 files

0.7.1

4 files

0.7.0

4 files

0.6.0

4 files

0.5.0

4 files

0.4.0

4 files

0.3.0

4 files

0.2.0

4 files

0.1.2

4 files

0.1.1

4 files

0.1.0

2 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