Skip to main content

A Python package for reading and writing DBF files, powered by a Rust core

Project description

fastdbf

fastdbf is a Rust-based reimplementation of the core ideas from ethanfurman/dbf, exposed as a Python package through PyO3.

The current focus is a practical Python-first package for reading and writing .dbf files, including Visual FoxPro-style nullable fields.

Performance Benchmark

Status

This project is in an early but usable state.

Implemented today:

  • read .dbf files from Python
  • inspect field metadata and field types
  • create new tables from DBF-style field specifications
  • append rows from dictionaries or tuples
  • write tables back to disk
  • Visual FoxPro null-flag support for nullable fields
  • a Rust core with test coverage for read/write roundtrips

Not implemented yet:

  • full memo file support (.dbt / .fpt)
  • full original dbf compatibility surface
  • record objects with attribute access like record.name
  • indexing, relations, PQL, and most advanced helpers from the original project

Installation

Create or sync the development environment with uv:

uv sync

Install into the current environment with uv:

uv pip install .

Editable install:

uv pip install -e .

Run tests:

uv run pytest

Build a wheel:

uv build

Quick Start

Read an existing DBF file:

import fastdbf

with fastdbf.Table("people.dbf").open("r") as table:
    print(table.kind)
    print(table.field_names)
    print(table.record_count)
    print(table.row(0))

    for field in table.fields():
        print(field["name"], field["type_code"], field["nullable"])

    for row in table:
        print(row)

Create and write a new DBF file:

import fastdbf

specs = "name C(25) null; age N(3,0) null; birth D null; active L null"
with fastdbf.Table("people.dbf", specs, dbf_type="vfp") as table:
    table.append({
        "NAME": "Spunky",
        "AGE": 23,
        "BIRTH": "1989-07-23",
        "ACTIVE": True,
    })

    table.append({
        "NAME": None,
        "AGE": None,
        "BIRTH": None,
        "ACTIVE": None,
    })

Field Types

Currently supported field types:

  • C Character
  • D Date
  • L Logical
  • N Numeric
  • F Float
  • I Integer
  • B Double
  • T / @ DateTime
  • Y Currency
  • M / G / P as reference values

Nullable fields are supported through null or nullable modifiers in the field specification:

"name C(25) null; amount N(10,2) nullable; created T null"

Nullable fields should be used with dbf_type="vfp" for Visual FoxPro-compatible null flags.

pandas Example

import pandas as pd
import fastdbf

with fastdbf.Table("input.dbf").open("r") as table:
    df = pd.DataFrame(list(table))
    df["NAME"] = df["NAME"].str.upper()

    field_specs = []
    for field in table.fields():
        code = field["type_code"]
        nullable = " null" if field["nullable"] else ""
        if code == "C":
            field_specs.append(f'{field["name"]} C({field["length"]}){nullable}')
        elif code in ("N", "F"):
            field_specs.append(
                f'{field["name"]} {code}({field["length"]},{field["decimals"]}){nullable}'
            )
        else:
            field_specs.append(f'{field["name"]} {code}{nullable}')

dbf_type = "vfp" if any(f["nullable"] for f in table.fields()) else "db3"
specs = "; ".join(field_specs)

with fastdbf.Table("output.dbf", specs, dbf_type=dbf_type) as out:
    for row in df.to_dict(orient="records"):
        out.append(row)

Performance & Columnar I/O (Arrow)

For maximum performance, especially with large datasets, fastdbf provides columnar read/write interfaces that avoid the high overhead of Python object allocation.

1. Apache Arrow Interface (Zero-Copy) — Fastest

Leverages the Arrow PyCapsule Interface to exchange data directly between Rust and Pandas / Polars / PyArrow without copying.

Read into Pandas via Arrow:

import fastdbf
import pyarrow as pa

with fastdbf.Table("data.dbf").open("r") as table:
    # Arrow Batch -> Pandas DataFrame
    df = pa.Table.from_batches([pa.record_batch(table.to_arrow())]).to_pandas()

Write from Pandas via Arrow:

import fastdbf
import pyarrow as pa

# Create Arrow batch from DataFrame
batch = pa.RecordBatch.from_pandas(df)

with fastdbf.Table("output.dbf", field_specs="NAME C(20); AGE N(10,2)") as table:
    table.extend_arrow(batch)

2. Columnar Interface (to_columns, extend_columns)

Reads/writes data as a dictionary of lists (one list per column). Faster than row-by-row processing but still bound by GIL limits.

Bulk Columnar Read:

import pandas as pd
import fastdbf

with fastdbf.Table("data.dbf").open("r") as table:
    cols = table.to_columns()
    df = pd.DataFrame(cols)

Bulk Columnar Write:

import pandas as pd
import fastdbf

# Assuming df ist das Pandas DataFrame
# Optionale interne Meta-Spalten wie '_deleted' entfernen
clean_data = {col: df[col].tolist() for col in df.columns if col != "_deleted"}

with fastdbf.Table("output.dbf", field_specs="NAME C(20); AGE N(10,2)") as table:
    table.extend_columns(clean_data)

Overview: Read/Write Methods compared

Method Implementation Pros
Row-by-Row table.row(), table.append() Easiest to use
Bulk Columnar to_columns(), extend_columns() No heavy dependencies
Zero-Copy Arrow to_arrow(), extend_arrow() Direct memory exchange

Documentation

Full Python API documentation:

Changelog:

Rust Example

use fastdbf::{Date, Table, Value};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut table = Table::new("name C(25); age N(3,0); birth D; qualified L")?;

    let mut record = table.new_record();
    record.insert(table.fields(), "name", Value::Character("Spunky".into()))?;
    record.insert(table.fields(), "age", Value::Numeric(23.0))?;
    record.insert(table.fields(), "birth", Value::Date(Some(Date::new(1989, 7, 23))))?;
    record.insert(table.fields(), "qualified", Value::Logical(Some(true)))?;
    table.push_record(record)?;

    table.write_to_path("example.dbf")?;
    Ok(())
}

License

This project is licensed under the Apache License 2.0.

Project details


Download files

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

Source Distribution

fastdbf-0.4.1.tar.gz (184.4 kB view details)

Uploaded Source

Built Distributions

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

fastdbf-0.4.1-cp311-abi3-win_amd64.whl (2.5 MB view details)

Uploaded CPython 3.11+Windows x86-64

fastdbf-0.4.1-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.4 MB view details)

Uploaded CPython 3.11+manylinux: glibc 2.17+ x86-64

fastdbf-0.4.1-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (2.2 MB view details)

Uploaded CPython 3.11+manylinux: glibc 2.17+ ARM64

fastdbf-0.4.1-cp311-abi3-macosx_11_0_arm64.whl (2.1 MB view details)

Uploaded CPython 3.11+macOS 11.0+ ARM64

fastdbf-0.4.1-cp311-abi3-macosx_10_12_x86_64.whl (2.3 MB view details)

Uploaded CPython 3.11+macOS 10.12+ x86-64

File details

Details for the file fastdbf-0.4.1.tar.gz.

File metadata

  • Download URL: fastdbf-0.4.1.tar.gz
  • Upload date:
  • Size: 184.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for fastdbf-0.4.1.tar.gz
Algorithm Hash digest
SHA256 f254067e51f32f19617303d47b70e7eaccac19b9f5748d9d182a712e6bfbcb8b
MD5 47192ae948ad99cddccbe1b637cee69c
BLAKE2b-256 6fa1f8ad3ba29b0f577d707ba4a8ddbdd6e8d764328d4b348b10c6b21e590c90

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastdbf-0.4.1.tar.gz:

Publisher: release.yml on Jonas-Bruns/fastdbf

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fastdbf-0.4.1-cp311-abi3-win_amd64.whl.

File metadata

  • Download URL: fastdbf-0.4.1-cp311-abi3-win_amd64.whl
  • Upload date:
  • Size: 2.5 MB
  • Tags: CPython 3.11+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for fastdbf-0.4.1-cp311-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 9df36cc1ab096e2c10ee78aff884b37c2dcc9558012d430bdf1c7d0103d4e33c
MD5 24616d15ac127afc10b5e72fd61b261f
BLAKE2b-256 5057a012a1f48521fe058c1913d061579532b8d8a641d0e656b5dfbafab12e04

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastdbf-0.4.1-cp311-abi3-win_amd64.whl:

Publisher: release.yml on Jonas-Bruns/fastdbf

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fastdbf-0.4.1-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for fastdbf-0.4.1-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 95f695adb9093e67e749575cb79d957ece0b3aa95645c8832be4abfd9f3ba3bf
MD5 ea57f365a43cbda88f61ce313c4cd37b
BLAKE2b-256 74728749c29c16abf6a7d7fcbe46e53b14c5041b0949c6ae5acd1af4cbbf9a3c

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastdbf-0.4.1-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on Jonas-Bruns/fastdbf

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fastdbf-0.4.1-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for fastdbf-0.4.1-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 73f968fbf679e9741797edc784d0203e33f6774cbaa2de459c823d038878b1d7
MD5 eeffa796724e9e2d54214b5c7431c434
BLAKE2b-256 bb05fd9d55fb547f2d2c8ccc1e9925ee22e919ce187d42f0730eb7dff60baec0

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastdbf-0.4.1-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on Jonas-Bruns/fastdbf

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fastdbf-0.4.1-cp311-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for fastdbf-0.4.1-cp311-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 63f8bcf2b455c732829a0047c25b507d9355fa7c19fdb48d0227de556aaee112
MD5 e5e211769b3a0c5f7ea729c9270b5566
BLAKE2b-256 b77a685e9f0b57df4315beb509b2f9c7d80b9f973f7899cdfc302600ad376f99

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastdbf-0.4.1-cp311-abi3-macosx_11_0_arm64.whl:

Publisher: release.yml on Jonas-Bruns/fastdbf

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fastdbf-0.4.1-cp311-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for fastdbf-0.4.1-cp311-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 479e965b3b634158b23ffba792fe88b568cd2950c9fe6bc75c69e626905da1ef
MD5 fabfa880bf019819b03c2c002c0296bf
BLAKE2b-256 a0f45ca02e3eabe01879f0934bddeaafa789ba861577eb6d890da42f7c680b45

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastdbf-0.4.1-cp311-abi3-macosx_10_12_x86_64.whl:

Publisher: release.yml on Jonas-Bruns/fastdbf

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page