LabSchema
LabSchema is a Python library that turns messy lab-style tables (CSV, TSV) into typed schemas with physical units and validation.
Features
- Declarative schemas — Define column names, types, units, and constraints once
- Physical units — Parse units from headers and convert values automatically via Pint
- Comprehensive validation — Get detailed error reports with row, column, and error codes
- Schema inference — Generate draft schemas from your data files
- Multiple exports — Export schemas as JSON or JSON Schema (draft 2020-12)
- CLI included — Validate files, infer schemas, and export from the command line
Installation
pip install labschema
For pandas DataFrame support:
pip install "labschema[pandas]"
Quick Start
30-Second Example
from labschema import TableSchema, Field, u
from labschema.io import read_csv
# Define your schema
schema = TableSchema(
name="plate_reader_run",
primary_key=("well",),
fields=[
Field("well", str, pattern=r"^[A-H](?:[1-9]|1[0-2])$"),
Field("absorbance", float, unit=u.dimensionless, ge=0),
Field("temperature", float, unit=u.degC, ge=-273.15),
],
)
# Validate your data
result = read_csv("run_042.csv", schema=schema)
if not result.ok:
result.report.print_summary()
else:
df = result.to_pandas() # Requires labschema[pandas]
print(f"Loaded {len(df)} valid rows")
Sample Output
run_042.csv: 96 rows, 93 valid, 4 errors, 1 warning
type_error (2)
line 14, column "absorbance": value "OVRFLW" is not a valid float
line 51, column "absorbance": value "n.d." is not a valid float
less_than_minimum (1)
line 22, column "temperature (°C)": value -300 is less than minimum -273.15 °C
duplicate_primary_key (1)
line 88: well "H12" already appears on line 97
extra_column (warning) (1)
column "Notes" does not match any field
CLI Usage
Validate a file
labschema validate data.csv --schema schema.json
Infer a schema from data
labschema infer data.csv --name my_schema -o schema.json
Export to JSON Schema
labschema export-schema schema.json --format jsonschema -o schema.jsonschema
Options
labschema validate --help
labschema infer --help
labschema export-schema --help
Schema Definition
Fields
from labschema import Field, u
# Basic string field
Field("name", str)
# Numeric with unit and bounds
Field("temperature", float, unit=u.degC, ge=-273.15)
# Nullable field
Field("notes", str, nullable=True)
# Field with enum constraint
Field("status", str, enum=["active", "inactive", "pending"])
# Field with regex pattern
Field("well", str, pattern=r"^[A-H][1-9]|1[0-2]$")
# Field with default value
Field("replicate", int, default=1)
# Field with custom validator
def positive(value):
if value <= 0:
raise ValueError("Must be positive")
return value
Field("count", int, validators=[positive])
TableSchema
from labschema import TableSchema, Field, u
schema = TableSchema(
name="experiment_data",
version="1.0",
description="Data from plate reader experiments",
primary_key=("sample_id", "replicate"),
extra_columns="warn", # "ignore", "warn", or "error"
fields=[
Field("sample_id", str),
Field("replicate", int, ge=1),
Field("absorbance", float, unit=u.dimensionless, ge=0),
Field("concentration", float, unit="mg/L", nullable=True),
],
metadata={
"instrument": "Synergy H1",
"protocol": "Standard absorbance",
},
)
Units
LabSchema uses Pint for unit handling. Units can be specified in:
- Field definitions:
Field("temp", float, unit=u.degC) - Column headers:
temperature (°C),concentration [mg/L]
Supported Aliases
| Input | Resolves to |
|---|---|
°C, degC |
degree_Celsius |
µL, μL, uL |
microliter |
% |
percent |
a.u., AU, RFU, OD |
dimensionless |
rpm |
revolutions_per_minute |
M |
mol/L |
Unit Conversion
Values are automatically converted from header units to field units:
# Field declares liters
Field("volume", float, unit="L")
# CSV header has milliliters
# volume [mL]
# 1000
# Result: volume = 1.0 (converted to liters)
Validation
Error Codes
| Code | Description |
|---|---|
missing_column |
Schema field has no matching header |
extra_column |
Header matches no field |
duplicate_column |
Multiple headers map to one field |
unit_incompatible |
Header unit incompatible with field unit |
row_length_mismatch |
Wrong number of cells in row |
null_not_allowed |
Missing value in non-nullable field |
type_error |
Value cannot be coerced to dtype |
less_than_minimum |
Violates ge/gt constraint |
greater_than_maximum |
Violates le/lt constraint |
not_in_enum |
Value not in enum |
pattern_mismatch |
String doesn't match pattern |
duplicate_primary_key |
Primary key already seen |
Accessing Results
result = read_csv("data.csv", schema=schema)
# Check if valid
if result.ok:
print("All data is valid!")
# Get valid records
records = result.to_records()
# Get as DataFrame (requires pandas)
df = result.to_pandas()
# Inspect errors
for error in result.errors:
print(f"{error.code}: {error.message}")
# Get detailed report
result.report.print_summary()
# JSON output
print(result.report.to_json())
Schema Inference
from labschema import infer_schema
# Infer from file
schema = infer_schema("data.csv", sample_rows=100, name="my_data")
# Save as JSON
schema.save("schema.json")
# Or get as Python code for editing
from labschema.infer import schema_to_python
print(schema_to_python(schema))
Export Formats
LabSchema JSON (round-trippable)
# Save
schema.save("schema.json")
# Load
schema = TableSchema.load("schema.json")
JSON Schema (draft 2020-12)
json_schema = schema.to_json_schema()
Reader Options
result = read_csv(
"data.csv",
schema=schema,
delimiter=";", # Auto-detected if not specified
decimal=",", # European decimal separator
thousands=" ", # Thousands separator to strip
encoding="utf-8-sig", # Handles BOM
skip_rows=2, # Skip preamble lines
comment="#", # Ignore comment lines
na_values=["NA", "-"], # Custom missing values
max_errors=100, # Stop after N errors
)
Development
# Clone the repository
git clone https://github.com/labschema/labschema.git
cd labschema
# Install development dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Run linting
ruff check src/ tests/
ruff format --check src/ tests/
# Type checking
mypy --strict src/
Contributing
See CONTRIBUTING.md for guidelines.
License
MIT License. See LICENSE for details.
Metadata
Release files for labschema 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| labschema-0.1.0.tar.gz | 36.0 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| labschema-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 66.3 kB
Release files / labschema-0.1.0.tar.gz
| Download URL | labschema-0.1.0.tar.gz |
|---|---|
| Size | 36.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7d195405d8fe392bce389b174406769ebd4a44e656e2ee853185c4d9737c0e73
|
|
BLAKE2b-256 checksum How to use checksums |
d27d2e12c22d83b3ec18d6a35d51a4778ab8bdf438b7d39a5a9201019b2219a0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.
Transparency logRelease files / labschema-0.1.0-py3-none-any.whl
| Download URL | labschema-0.1.0-py3-none-any.whl |
|---|---|
| Size | 30.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2a6ee244b56d29a5e312e645e52d5c17e7f13e89b8dc3dd7cae7f3388c73cfd6
|
|
BLAKE2b-256 checksum How to use checksums |
32c53c57aa5a0828a7e2dcb7106f81038728425e840065215f068df7b8a5f83c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.
Transparency logSecurity for labschema 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for labschema-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 13, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.