Skip to main content

csv-turbo

High-performance CSV reader/writer for Python — streaming, typed columns, large files.

PyPI version Python License: MIT

Features

  • Streaming by default — iterate rows without loading the entire file into memory
  • Typed columns — declare int, float, bool, date, datetime schemas and get cast values automatically
  • Schema validation — catch missing/extra columns and type errors early
  • Dialect detection — auto-detect delimiter, quoting style, and line endings
  • Pipeline API — composable lazy transformations: filter, map, select, rename, chunk, sort, unique
  • Column statistics — profile any CSV with counts, nulls, min/max, mean, std dev, top-N values
  • Built-in dialects — RFC 4180, TSV, semicolon, pipe, Excel presets
  • Zero dependencies — pure Python ≥ 3.9, standard library only

Installation

pip install csv-turbo

Quick Start

Reading

from csv_turbo import CsvReader

for row in CsvReader("data.csv"):
    print(row["name"], row["score"])

Writing

from csv_turbo import CsvWriter

rows = [
    {"id": 1, "name": "Alice", "score": 9.5},
    {"id": 2, "name": "Bob",   "score": 8.0},
]

with CsvWriter("output.csv") as w:
    w.writerows(rows)

Typed Schema

from csv_turbo import CsvReader, Schema, ColumnDef, INT, FLOAT, STRING, DATE

schema = Schema([
    ColumnDef("id",    INT,    nullable=False),
    ColumnDef("name",  STRING),
    ColumnDef("score", FLOAT,  nullable=True, default=0.0),
    ColumnDef("dob",   DATE),
])

for row in CsvReader("data.csv", schema=schema):
    # row["id"] is int, row["score"] is float, row["dob"] is datetime.date
    print(row["id"], row["score"])

Streaming Large Files (Chunked)

from csv_turbo import CsvReader

reader = CsvReader("huge_file.csv")
for batch in reader.chunks(500):
    db.bulk_insert(batch)           # list of 500 row dicts

Pipeline API

from csv_turbo import CsvReader
from csv_turbo.streaming import Pipeline

result = (
    Pipeline(CsvReader("sales.csv", schema=schema))
    .filter(lambda r: r["amount"] > 100)
    .map(lambda r: {**r, "vat": round(r["amount"] * 0.2, 2)})
    .select("id", "name", "amount", "vat")
    .sort(key=lambda r: r["amount"], reverse=True)
    .take(50)
    .to_list()
)

Write pipeline output directly to CSV:

Pipeline(CsvReader("raw.csv"))     \
    .where(status="active")        \
    .drop("internal_notes")        \
    .write_csv("clean.csv")

Dialect Detection

from csv_turbo.dialect import detect_dialect_from_file

dialect = detect_dialect_from_file("european_export.csv")
print(dialect.delimiter)   # likely ";"

for row in CsvReader("european_export.csv", delimiter=dialect.delimiter):
    ...

Use a preset dialect:

from csv_turbo import TSV, CsvReader

for row in CsvReader("data.tsv", delimiter=TSV.delimiter):
    ...

Column Statistics / Profiling

from csv_turbo import CsvReader, profile

rows = CsvReader("data.csv").read_all()
data_profile = profile(rows, top_n=5)
print(data_profile)

# Access per-column stats
stats = data_profile.column("score")
print(stats.mean, stats.std_dev, stats.null_count)

Infer Schema Automatically

from csv_turbo import CsvReader

schema = CsvReader.infer_schema("data.csv", sample_size=500)
print(schema)   # Schema([id:int, name:string, score:float, dob:date])

for row in CsvReader("data.csv", schema=schema):
    print(row)

Read from String (Testing / Inline Data)

from csv_turbo import CsvReader

csv_text = "id,name,score\n1,Alice,9.5\n2,Bob,8.0\n"
for row in CsvReader.from_string(csv_text):
    print(row)

Write to String

from csv_turbo import CsvWriter

csv_str = CsvWriter.to_string([
    {"x": 1, "y": 2},
    {"x": 3, "y": 4},
])
print(csv_str)

API Reference

CsvReader

CsvReader(
    source,            # str | Path | file-like
    *,
    schema=None,       # Schema for typed casting
    delimiter=",",
    quotechar='"',
    encoding="utf-8",
    has_header=True,
    skip_blank_lines=True,
    strip_whitespace=True,
    null_values={""},  # Values treated as None
    row_filter=None,   # Callable[[dict], bool]
    row_transform=None,# Callable[[dict], dict]
    strict=False,      # Raise on extra columns
    max_errors=0,      # Tolerated cast errors
)
Method / Property Description
__iter__() Iterate rows as dicts
chunks(size) Iterate in batches
read_all() Load all rows into a list
count_rows() Count without materialising
headers Column names after first read
error_count Cast errors encountered
CsvReader.from_string(text) Create from a CSV string
CsvReader.infer_schema(path) Auto-detect schema

CsvWriter

CsvWriter(
    destination,           # str | Path | file-like
    *,
    fieldnames=None,       # Column order
    delimiter=",",
    quotechar='"',
    encoding="utf-8",
    write_header=True,
    formatter=None,        # Callable[[Any], str]
    column_formatters={},  # Per-column formatters
    row_transform=None,
    append=False,
    buffer_size=8192,
)
Method Description
writerow(row) Write one dict row
writerows(rows) Write an iterable of rows
rows_written Count of rows written
CsvWriter.to_string(rows) Render to string

Schema & ColumnDef

Schema([
    ColumnDef(name, type, nullable=True, default=None, alias=None),
    ...
])

Built-in type singletons: STRING, INT, FLOAT, BOOL, DATE, DATETIME

Parameterised constructors: IntType(min_value=0), FloatType(precision=2), DateType(fmt="%d/%m/%Y"), StringType(max_length=255)

Pipeline

Method Description
.filter(fn) Keep rows where fn(row) is True
.map(fn) Transform each row
.select(*cols) Keep only named columns
.rename(mapping) Rename columns
.drop(*cols) Remove columns
.add_field(name, fn) Compute a new column
.where(**kwargs) Equality filter shorthand
.skip(n) Skip first n rows
.take(n) Keep first n rows
.chunk(size) Group into batches
.sort(key) Sort (materialises)
.unique(key) Deduplicate rows
.peek(fn) Side-effect per row
.to_list() Materialise to list
.to_dict(key) Index by column
.count() Count rows
.first() First row or None
.aggregate(col, ...) Sum/mean/min/max
.write_csv(path) Write to file

profile(rows)

data_profile = profile(rows, top_n=10)
# DataProfile.row_count, .columns, .column(name)
# ColumnStats.count, .null_count, .fill_rate, .unique_count
# ColumnStats.mean, .std_dev, .min_value, .max_value, .median (numeric)
# ColumnStats.min_length, .max_length, .avg_length (string)
# ColumnStats.top_values — list of (value, count)

Error Handling

All exceptions inherit from CsvTurboError:

Exception When
ParseError Malformed CSV structure
TypeCastError Value cannot be cast to declared type
SchemaValidationError Missing/extra columns
WriteError Write failure
ConfigurationError Invalid reader/writer options
from csv_turbo import CsvReader, TypeCastError, SchemaValidationError

try:
    for row in CsvReader("data.csv", schema=schema, max_errors=5):
        process(row)
except TypeCastError as e:
    print(f"Bad value '{e.value}' in column '{e.column}' on line {e.line}")
except SchemaValidationError as e:
    print(f"Missing columns: {e.missing_columns}")

License

MIT © Vladyslav Zaiets

Metadata

Release files for csv-turbo 1.0.0

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

Source distribution (sdist)

Source distribution for csv-turbo 1.0.0
File Size Uploaded
csv_turbo-1.0.0.tar.gz 19.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for csv-turbo 1.0.0
File Interpreter ABI Platform
csv_turbo-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 43.2 kB

Release files / csv_turbo-1.0.0.tar.gz

Download URL csv_turbo-1.0.0.tar.gz
Size 19.0 kB
Tags Source
SHA-256 checksum
How to use checksums
4a6181e23dfc36efebaaa32723c876b3d23425d0c1461b9312e42ec7854286f0
BLAKE2b-256 checksum
How to use checksums
01ea13d2c24957c12cb10e3f83d125f3582deea6d22a5326bdce28ef84cba729
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Release files / csv_turbo-1.0.0-py3-none-any.whl

Download URL csv_turbo-1.0.0-py3-none-any.whl
Size 24.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2b8675d8eec067608e71ca2f96369d8e24f3f54f3c300e47e619abffd16ab5d6
BLAKE2b-256 checksum
How to use checksums
d8a4fb963089f7a3a33ea19f806da87176b65ccba3ea0915bb481272818fcb8a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Release history Release notifications | RSS feed

This release

1.0.0 This release

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