Export¶

3LC Tables can be exported to common formats like CSV, COCO, YOLO, and JSON using the Python API or the CLI. The built-in exporters handle the conversion, including weight-based row filtering, format inference, and format-specific options like image path handling.

If none of the built-in formats fit, you can write a custom exporter — as simple as a single method — and plug it in so it works with both the API and CLI automatically.

Quick Start¶

Python API¶

import tlc

table = tlc.Table.from_url("path/to/table")

# Format inferred from extension and table content
table.export("output.csv")

# Explicit format and options
table.export("annotations.json", format="coco", indent=2, image_folder="/images")

CLI¶

# Format inferred
3lc export path/to/table.json output.csv

# Explicit format and options
3lc export path/to/table.json annotations.json --format coco --coco-indent 2
3lc export path/to/table.json ./dataset --format yolo --yolo-split train

CLI options are auto-generated from each exporter’s parameters and prefixed by format name. Run 3lc export --help to see all available options.

Built-in Formats¶

Format

Extension

Description

csv

.csv

Flat column export with configurable dialect

json

.json

Row-oriented JSON

coco

.json

COCO object detection / segmentation / keypoints

yolo

(directory)

Ultralytics YOLO directory structure

Format Inference¶

When no --format is specified, 3LC picks the best exporter by checking each exporter’s can_export() method against the table content and output path. For example, a table with bounding boxes exported to a .json file will automatically select the COCO exporter over the generic JSON exporter. If multiple exporters match, the one with the highest priority wins.

Priority values for the built-in formats:

Format

Priority

Notes

coco

3

Beats json for .json outputs when the table has COCO-compatible annotation columns

yolo

2

Directory output; picked for tables with bounding boxes when the output URL has no extension

csv

1

Default for .csv

json

1

Default for .json when coco doesn’t match

Custom exporters can set any integer priority — higher wins. If two registered formats tie at the highest priority and both accept the table, Table.export() raises ValueError and asks you to specify format explicitly.

Format-Specific Options¶

Each exporter declares typed parameters that become keyword arguments in Python and CLI options on the command line:

table.export(
    "annotations.json",
    format="coco",
    image_folder="/data/images",     # Make image paths relative to this folder
    absolute_image_paths=False,      # Or make them absolute
    annotation_column_name=None,     # Auto-detected if omitted
    image_column_name="image",       # Column containing image URLs
    per_image_extras=None,           # Extra image-level columns to include
    indent=4,                        # JSON indentation
)
table.export(
    "./my_dataset",
    format="yolo",
    split="train",                   # Split name for directory structure
    image_strategy="symlink",        # "ignore", "copy", "move", or "symlink"
    image_column_name="image",       # Column containing image URLs
    annotation_column_name=None,     # Auto-detected if omitted
    dataset_name="dataset",          # Name for the YAML config file
)
table.export(
    "output.csv",
    format="csv",
    dialect="excel",                 # Any csv.Dialect name
    exclude_header=False,            # Omit the header row
)
table.export(
    "output.json",
    format="json",
    indent=4,                        # JSON indentation
)

Weight Filtering¶

All exporters support a weight_threshold parameter (default 0.0). Rows with a weight below this threshold are excluded from the export. This lets you export only the rows you’ve marked as relevant in the Dashboard:

table.export("cleaned.csv", weight_threshold=0.5)

In-Memory Export¶

To export the data in a Table to a Pandas DataFrame:

df = table.to_pandas()

Listing Registered Exporters¶

To see which exporters are available in your environment:

3lc exporters list

Or from Python:

from tlc.export import list_exporters

for info in list_exporters():
    print(f"{info['format']:10s} {info['source']}")

Each entry is an ExporterInfo dict with format, exporter_class, module, and source (one of "builtin", "entrypoint", "config", or "runtime").

Custom Exporters¶

Do you need this section?

If you’re using a built-in format, you can skip this. Custom exporters are for adding new output formats — for example, exporting to a domain-specific annotation tool, a database, or a proprietary format.

There are three patterns, from simplest to most flexible:

RowExporter — One Row at a Time¶

The simplest option. Implement a single method that converts one row to a string, and the framework handles iteration, weight filtering, and file writing:

import json
from tlc.export import RowExporter, register_exporter

@register_exporter
class NdJsonExporter(RowExporter):
    """Export table rows as newline-delimited JSON."""
    supported_format = "ndjson"
    file_extensions = frozenset({".ndjson", ".jsonl"})
    separator = "\n"

    def export_row(self, row: dict, **kwargs: object) -> str:
        return json.dumps(row, default=str)

SerializingExporter — Whole Table to String¶

When you need access to the full table (e.g. to write a header, or to produce a format that isn’t line-oriented), implement serialize():

from tlc.export import SerializingExporter, register_exporter

@register_exporter
class MarkdownExporter(SerializingExporter):
    """Export a table as a Markdown table."""
    supported_format = "markdown"
    file_extensions = frozenset({".md"})

    def serialize(self, table, output_url, weight_threshold: float = 0.0, **kwargs) -> str:
        rows = list(self.remaining_table_rows(table, weight_threshold))
        if not rows:
            return ""
        headers = list(rows[0].keys())
        lines = ["| " + " | ".join(headers) + " |"]
        lines.append("| " + " | ".join("---" for _ in headers) + " |")
        for row in rows:
            lines.append("| " + " | ".join(str(row.get(h, "")) for h in headers) + " |")
        return "\n".join(lines)

Exporter — Full Control¶

For formats that write multiple files or directories (like YOLO), subclass tlc.export.exporter.Exporter directly and override its internal export hooks (_do_export and _get_export_impl_method). The latter points the CLI at your main method so its parameters are introspectable.

See the built-in YoloExporter for a complete example of this pattern.

Plugin Registration¶

Custom exporters defined in third-party packages can be discovered automatically via Python entry points:

# pyproject.toml
[project.entry-points."tlc.exporters"]
ndjson = "my_package.exporters:NdJsonExporter"

3LC discovers entry points lazily — your package just needs to be installed. The entry point should reference the class (not an instance); 3LC will instantiate it automatically. Installed plugins show up in 3lc exporters list with source=entrypoint.

Alternatively, use the tlc.export.register_exporter decorator as shown above for exporters defined in your own codebase.

A minimal end-to-end plugin example — project layout, pyproject.toml, and the exporter class — lives in 3lc-examples/examples/tlc-ndjson-exporter.

CLI Option Naming¶

The 3lc export command auto-generates a CLI option for each format-specific parameter. The naming convention is:

  • --<format>-<argname-with-dashes> for regular values — e.g. --coco-image-folder /data/images, --yolo-split train.

  • A bare flag --<format>-<argname-with-dashes> for boolean parameters whose default is False — e.g. --csv-exclude-header, --coco-absolute-image-paths.

Boolean parameters whose default is None (tri-state, like --coco-include-segmentation) take an explicit true/false/none argument.

Run 3lc export --help to see the exact options exposed by all registered exporters in your environment.

Errors and Troubleshooting¶

Unknown export format 'foo'. Available formats: ...

The requested format is not registered. Run 3lc exporters list (or ExporterRegistry.list_exporters() from Python) to see what is available. If you expected a third-party plugin to be present, confirm the package is installed in the same environment as 3lc and that its pyproject.toml declares an entry point in the tlc.exporters group.

Table {url} is not in the correct format for {fmt} export.

The chosen exporter’s can_export() returned False. The most common cause is a missing annotation column — e.g. exporting to COCO from a table without bbs, segmentations, or keypoints_2d. Check the exporter’s docstring for required columns, or use --format csv / --format json for a format-agnostic export.

Multiple export formats with the highest priority found ...

Two registered exporters tied at the highest priority and both said can_export=True. Pass --format explicitly to break the tie.

CLI --help is missing options you expected

If a registered third-party exporter fails to import at CLI startup, its options are skipped and a warning is logged. Re-run with --log-level DEBUG to see the traceback.

For further details, see the API reference.