Writers

CSVWriter, ExcelWriter, ParquetWriter, and PDFWriter read a source file and export it to other formats. All accept a string path or pathlib.Path. Values are written verbatim — Datagrunt does not sanitize output; see Formula Injection Safety for spreadsheet-format caveats.


CSVWriter

CSVWriter(filepath, engine="duckdb", lenient=False, normalize_columns=False)
Parameter Type Default Description
filepath str | Path required Path to the source CSV file.
engine str "duckdb" "duckdb", "polars", or "pyarrow". See CSV Engines.
lenient bool False Gracefully handle ragged rows before export. See Handling Messy CSV.
normalize_columns bool False Write with normalized column names. See Column Name Normalization.

Methods

Method Description
write_csv(out_filename=None) Writes to a CSV file.
write_excel(out_filename=None) Writes to an Excel file.
write_json(out_filename=None) Writes to a JSON file.
write_json_newline_delimited(out_filename=None) Writes to newline-delimited JSON.
write_parquet(out_filename=None) Writes to a Parquet file.

ExcelWriter

ExcelWriter(filepath, normalize_columns=False, **read_options)

Mirrors ExcelReader’s constructor (same parameters — see ExcelReader) and shares the same per-sheet model. Every method below accepts sheet=None (name or zero-based position; defaults to the first sheet) and all_sheets=False. Passing both sheet and all_sheets=True raises ValueError. See Selecting Worksheets.

Methods

Method Description
write_csv(out_filename=None,
          sheet=None,
          all_sheets=False,
          **read_options)
Writes the selected sheet, or one file per sheet. Read options.
write_excel(out_filename=None,
            sheet=None,
            all_sheets=False,
            **read_options)
Writes the selected sheet, or every sheet into one multi-tab workbook. Read options.
write_json(out_filename=None,
           sheet=None,
           all_sheets=False,
           **read_options)
Writes the selected sheet(s) to JSON. Read options.
write_json_newline_delimited(
    out_filename=None,
    sheet=None,
    all_sheets=False,
    **read_options)
Writes the selected sheet(s) to newline-delimited JSON. Read options.
write_parquet(out_filename=None,
              sheet=None,
              all_sheets=False,
              **read_options)
Writes the selected sheet(s) to Parquet. Read options.

The **read_options parameter

**read_options controls how the source workbook is read before export (the writer reads the sheet, then writes it out): any Polars read_excel keyword — e.g. write_csv('out.csv', has_header=False) to treat the first row as data, or skip_rows=2 to skip a preamble. Constructor options apply to every export; per-call options are merged over them and win. See Polars Read-Option Passthrough.

All methods honor the constructor’s normalize_columns setting.


ParquetWriter

ParquetWriter(filepath, normalize_columns=False, **read_options)

Mirrors ParquetReader’s constructor (same parameters — see ParquetReader); **read_options on the constructor controls how the source Parquet is read before export. Empty/blank source files produce a single empty (0-byte) output file rather than raising.

Methods

Method Description
write_csv(out_filename=None,
          **write_options)
Writes to a CSV file. Write options.
write_excel(out_filename=None,
            **write_options)
Writes to an Excel file. Write options.
write_json(out_filename=None,
           **write_options)
Writes to a JSON file. Write options.
write_json_newline_delimited(
    out_filename=None,
    **write_options)
Writes to newline-delimited JSON. Write options.
write_parquet(out_filename=None,
              **write_options)
Re-encodes to Parquet. Write options · Parquet Options guide.

The **write_options parameter

**write_options controls how the output file is written: any keyword accepted by the matching Polars writer — write_csv (e.g. separator=';'), write_excel (e.g. autofit=True), write_parquet (e.g. compression='zstd'), and so on. For example: write_parquet('recompressed.parquet', compression='zstd').

All methods honor the constructor’s normalize_columns setting.


PDFWriter

PDFWriter(
    source,
    *,
    password=None,
    workers=1,
    ocr="auto",
    dpi=200,
    vision_dpi=300,
    max_render_pixels=16_000_000,
    min_image_dimension=40,
    strict=False,
)

Requires the pdf extra. Takes the same options as PDFReader, checked the same way at construction. The PDF is extracted on the first call that needs it, then cached for the writer’s life; the writer holds no file, handle, or process between calls, so there is nothing to close.

Parameter Type Default Description
source str | os.PathLike | PDFDocument required A PDF path, or a PDFDocument (such as reader.document) to write as it is, without extracting again. A missing path raises FileNotFoundError; a path that is not a PDF raises ValueError.
password str | None None Keyword-only. An encrypted PDF’s password.
workers int 1 Keyword-only. Processes to extract pages with (at least 1); render_pages_as_images and write_bundle also render that many pages at a time. See Concurrency & Environments.
ocr str "auto" Keyword-only. "auto", "always", or "never". See Scanned pages and OCR.
dpi int 200 Keyword-only. The DPI of page images (at least 36): render_pages_as_images’ default and the bundle’s renders.
vision_dpi int 300 Keyword-only. The DPI of pages read by OCR (at least dpi).
max_render_pixels int 16_000_000 Keyword-only. Caps the pixels of every render (at least 262,144): a very large page renders at a lower DPI.
min_image_dimension int 40 Keyword-only. Embedded images narrower or shorter than this many pixels are not figures (at least 1). See Filtering Small Embedded Images.
strict bool False Keyword-only. Raise PDFCorruptError on a bad page instead of recording it as an error page.

Methods

Method Returns Description
write_json(out_filepath) Path Writes the whole document as compact ASCII JSON — lossless and versioned. Reload it with PDFReader(json.loads(...)).
write_jsonl(out_filepath) Path Writes one element row per line as compact UTF-8 JSON: bbox an object, scope_path and hidden_reasons arrays.
write_json_newline_delimited(out_filepath) Path write_jsonl under its 4.x name.
write_markdown(out_filepath,
               *,
               include_hidden=False)
Path Writes the document’s Markdown, UTF-8. Hidden elements are left out unless include_hidden=True, which keeps each behind its <!-- hidden: ... --> marker.
write_parquet(out_filepath,
              **polars_kwargs)
Path Writes the element rows as Parquet, nested types kept. polars_kwargs go to Polars write_parquet (e.g. compression='zstd').
write_csv(out_filepath,
          **polars_kwargs)
Path Writes the element rows as CSV, flattened: bbox as bbox_x0, bbox_y0, bbox_x1, bbox_y1; scope_path and hidden_reasons as JSON-array strings. polars_kwargs go to Polars write_csv (e.g. separator=';'). Values are written verbatim (see formula injection).
extract_images(output_dir,
               *,
               dedupe=True)
list[Path] Writes each figure as a PNG into output_dir: each distinct picture once as <sha256>.png (another picture of the same stream as <sha256>-<its PNG's SHA-256>.png), or, with dedupe=False, every figure as <element_id>.png (p0001_e003.png). A figure whose bytes can’t be read is logged and skipped. See Figures.
render_pages_as_images(
    output_dir,
    *,
    dpi=None)
list[Path] Renders every page as an 8-bit grayscale page_NNNN.png at dpi (at least 36), or the writer’s dpi when None, capped by max_render_pixels, in a memory-capped worker. A page that can’t be rendered is logged and skipped. Raises ValueError on a writer built from a PDFDocument. See Page images.
write_bundle(output_dir,
             *,
             overwrite=False)
PDFDocument Writes the bundle — json/document.json, json/elements.jsonl, markdown/document.md, markdown/pages/page_NNNN.md, figures, page images, and a checksummed manifest.json — atomically. A bundle already there of the same PDF, options, and datagrunt version is returned as it is; overwrite=True replaces any other valid bundle. output_dir must otherwise not exist or be empty — a directory without a valid bundle manifest is never overwritten — and its parent must exist. Returns the document with its file paths set; PDFReader(output_dir) loads it back, verified. Raises ValueError on a writer built from a PDFDocument.

Every output path is required — there are no default filenames — and every path returned is absolute. Each file is written atomically (a temporary file beside the target, then a rename), so a failed write never leaves a partial file; an existing file is replaced, and missing directories are created (except for write_bundle). See Writing outputs.