A fast excel file reader for Python and Rust.
Docs:
The Python library is considered production-ready. The API is mostly stable, and we avoid breaking changes as much as possible. v1.0.0 will be released once the milestone is reached.
The Rust crate is still experimental, and breaking changes are to be expected.
# Lightweight installation (no PyArrow dependency)
pip install fastexcel
# With Polars support only (no PyArrow needed)
pip install fastexcel[polars]
# With Pandas support (includes PyArrow)
pip install fastexcel[pandas]
# With PyArrow support
pip install fastexcel[pyarrow]
# With all integrations
pip install fastexcel[pandas,polars]
FastExcel supports the Arrow PyCapsule Interface for zero-copy data exchange with libraries like Polars, without requiring pyarrow as a dependency. Use fastexcel with any Arrow-compatible library without requiring pyarrow.
import fastexcel
# Load an Excel file
reader = fastexcel.read_excel("data.xlsx")
sheet = reader.load_sheet(0) # Load first sheet
# Use with Polars (zero-copy, no pyarrow needed)
import polars as pl
df = pl.DataFrame(sheet) # Direct PyCapsule interface
print(df)
# Or use the to_polars() method (also via PyCapsule)
df = sheet.to_polars()
print(df)
# Or access the raw Arrow data via PyCapsule interface
schema = sheet.__arrow_c_schema__()
array_data = sheet.__arrow_c_array__()
import fastexcel
reader = fastexcel.read_excel("data.xlsx")
sheet = reader.load_sheet(0)
# Convert to pandas (requires `pandas` extra)
df = sheet.to_pandas()
# Or get pyarrow RecordBatch directly
record_batch = sheet.to_arrow()
reader = fastexcel.read_excel("data.xlsx")
# List available tables
tables = reader.table_names()
print(f"Available tables: {tables}")
# Load a specific table
table = reader.load_table("MyTable")
df = pl.DataFrame(table) # Zero-copy via PyCapsule, no pyarrow needed
- Zero-copy data exchange via Arrow PyCapsule Interface
- Flexible dependencies - use with Polars (no PyArrow needed) or Pandas (includes PyArrow)
- Seamless Polars integration -
pl.DataFrame(sheet)
andsheet.to_polars()
work without PyArrow via PyCapsule interface - High performance - written in Rust with calamine and Apache Arrow
- Memory efficient - lazy loading and optional eager evaluation
- Type safety - automatic type inference with manual override options
You'll need:
- Rust - Rust stable or nightly
- uv - Fast Python package manager (will install Python 3.9+ automatically)
- git - For version control
- make - For running development commands
Python Version Management: uv handles Python installation automatically. To use a specific Python version:
uv python install 3.13 # Install Python 3.13
uv python pin 3.13 # Pin project to Python 3.13
# Clone the repository (or from your fork)
git clone https://github.com/ToucanToco/fastexcel.git
cd fastexcel
# First-time setup: install dependencies, build debug version, and setup pre-commit hooks
make setup-dev
Verify your installation by running:
make
This runs a full development cycle: formatting, building, linting, and testing
Run make help
to see all available commands, or use these common ones:
make all # full dev cycle: format, build, lint, test
make install # install with debug build (daily development)
make install-prod # install with release build (benchmarking)
make test # to run the tests
make lint # to run the linter
make format # to format python and rust code
make doc-serve # to serve the documentation locally
python/fastexcel/_fastexcel.pyi
- Python API typespython/tests/
- Comprehensive usage examples
For benchmarking, use make benchmarks
which automatically builds an optimised wheel.
This is required for profiling, as dev mode builds are much slower.
make benchmarks
mprof run -T 0.01 python python/tests/benchmarks/memory.py python/tests/benchmarks/fixtures/plain_data.xls
- Create a PR containing a commit that only updates the version in
Cargo.toml
. - Once it is approved, squash and merge it into main.
- Tag the squashed commit, and push it.
- The
release
GitHub action will take care of the rest.
- Use
cargo check
to verify that your rust code compiles, no need to go throughmaturin
every time cargo clippy
= 💖- Careful with arrow constructors, they tend to allocate a lot
mprof
andtime
go a long way for perf checks, no need to go fancy right from the start