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 free-threaded build is still considered experimental
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.10+ 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-devVerify your installation by running:
makeThis 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 locallypython/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 benchmarksmprof 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
releaseGitHub action will take care of the rest.
- Use
cargo checkto verify that your rust code compiles, no need to go throughmaturinevery time cargo clippy= 💖- Careful with arrow constructors, they tend to allocate a lot
mprofandtimego a long way for perf checks, no need to go fancy right from the start