Library / SDK
xlwings/xlwings avatar
xlwings/xlwings

xlwings has three dependencies on two platforms and none on Linux, and Windows still builds through setup.py

xlwings is a Python library that makes it easy to call Python from Excel and vice versa. It works with Excel on Windows, macOS, and Excel on the web.

3,415 stars537 forksPythonNOASSERTION

At a glance

What is it?
xlwings/xlwings is the BSD-licensed bridge between Python and Excel from Felix Zumstein, with releases 0.37.3, 0.37.4 and 0.37.5 and a last push on 2026-09-27. The build configuration is the interesting part: a Rust extension built by maturin for most platforms, setup.py for Windows, and a Cargo dependency pinned to a commit inside a fork.
Who is it for?
xlwings is the right tool when the workbook itself has to call your Python, because the open source tier covers scripting, macros and, on Windows, user defined functions. It is the wrong tool for reading spreadsheets on a server, since the Rust reader exists but a headless read path is a PRO feature.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 8 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 4, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Two build backends, and Windows is the one still on the old path

pyproject.toml declares a Rust-backed build:

code
[build-system]
requires = ["maturin>=1,<2"]
build-backend = "maturin"

There is also a setup.py at the root, and its docstring says why:

Windows builds currently rely on setup.py instead of pyproject.toml/maturin as long as the dlls are distributed as data_files.

So a single repository builds two different ways. Everything except Windows goes through maturin and the Rust extension module; Windows goes through setuptools, and the reason is an old packaging mechanism, data_files, that places the DLLs next to the interpreter. There is a further branch: if the environment variable `BUILD_RUST` is set to 1, setup.py imports setuptools_rust, so the two paths can be merged explicitly.

The tree explains the rest. There is a Cargo.toml, a Cargo.lock and a `.cargo/` directory at the top level, alongside a `xlwingsdll/` directory holding the Windows binaries. The Rust crate is a cdylib named xlwings, built with pyo3, and it is not an optimisation detail: the Rust side is where Excel files are read.

One constraint is written into the manifest as a comment. abi3 wheels are not supported because DateTime is not part of the ABI specification referenced as PEP 384, so each Python version needs its own wheel rather than one stable ABI wheel.

The Rust side pulls from a fork pinned to a commit hash

Cargo.toml lists three dependencies. Two are ordinary: chrono with serde, and pyo3 at 0.29.0 with the extension-module and chrono features.

The third is not. calamine is declared as a git dependency pointing at a repository under the same organisation, pinned to a specific revision:

code
calamine = {git = "https://github.com/xlwings/calamine", rev = "ed0a4bde9ae0d0abaeeaed26b0fbd5b20cce91b8", features = ["dates"] }

That is a fork rather than the upstream crate, and a commit hash rather than a version number. The practical consequences are the ones you would expect from any git-pinned dependency. The build is not reproducible from the upstream registry, so a rebuild months later fetches the same commit rather than the newest compatible release, which is a deliberate stability choice and also means you inherit whatever that commit contains. And the `dates` feature is enabled, which is the date-parsing support the extension needs.

Cargo.lock is committed at the root, which pins the rest of the graph, and the presence of a `.cargo/` directory suggests the source or registries for Cargo are configured in the repository too.

For anyone auditing what ends up inside an installed xlwings wheel, this is the line to start from.

Three dependencies, all of them platform-gated, so a Linux install has none

The dependency list is three entries long and every one has a marker:

code
dependencies = [
    "pywin32 >= 224;platform_system=='Windows'",
    "psutil >= 2.0.0;platform_system=='Darwin'",
    "appscript >= 1.0.1;platform_system=='Darwin'",
]

pywin32 on Windows, and psutil plus appscript on macOS. On Linux the resolved list is empty.

That follows from what the library does. Excel on Windows is driven through the COM object model, which is what pywin32 provides; Excel on macOS is driven through AppleScript, which is what appscript provides, with psutil for process inspection. Neither exists on Linux, and the library's own position is that Excel does not run there.

It also means the packaging is honest in a way many cross-platform packages are not. A Linux install pulls nothing, which is why the README's claim that the package works on Windows and macOS is a statement about the Excel versions rather than about the operating systems.

Optional extras are separate. `reports` brings Jinja2, pdfrw and mistune. `all` is a development bundle including pandas, matplotlib, plotly, flask, requests and pytest. `vba_edit` brings watchgod, which is the only extra tied to a specific feature rather than to a report or a test.

The open source package excludes a subpackage that sits in the same tree

The README states the packaging rule in one line: the package includes all files in the xlwings package except the `pro` folder, that is, the xlwings.pro subpackage.

So the repository is one tree containing two products. The BSD-licensed open source library is what an ordinary install gets, and the pro subpackage is present in the source but not shipped. Nothing else in the packaging configuration needs to say so.

That is worth knowing before you read the source, because the feature list you will see in the tree is wider than the feature list you can rely on. The README draws the line explicitly in three separate places.

The three tiers are distinct products rather than feature flags. The open source tier gives you scripting from Python, a VBA-like syntax, and the option of replacing macros with Python code. User defined functions written in Python are marked as Windows only. Then there is xlwings Lite, installed from Excel's add-in store rather than from a package index, which needs no local Python, works on Windows, macOS and Excel on the web including the free version of Excel, supports custom functions, gives access to the Excel object model, stores the Python inside the workbook, and is free for personal and commercial use. Then PRO, which is a paid tier in everything but one case.

The noncommercial PRO key is the word noncommercial, printed in the README

PRO is described as source-available rather than open source, and dual-licensed. One option is the PolyForm Noncommercial License 1.0.0, under which noncommercial use is free. The other is the xlwings PRO License, under which commercial use requires a paid plan.

A licence key is installed from a terminal:

code
xlwings license update -k YOUR_LICENSE_KEY

or supplied through the environment variable `XLWINGS_LICENSE_KEY`.

The key for the noncommercial path is stated in the file with no retrieval step: to use xlwings PRO for free in a noncommercial context, use the key `noncommercial`. There is nothing to request and nothing to wait for. For a commercial context you request a trial key, and beyond the trial you need a paid plan, which is also where support and the ability to create one-click installers come from.

So the whole licensing conversation reduces to one question: is this commercial use. The answer selects one of two licence texts, and the noncommercial branch is usable immediately.

That is also why the repository records no licence in its settings while the package metadata says BSD 3-clause. There are two licence files at the root, LICENSE.txt and LICENSE_PRO.txt, and a detector asked to classify the repository has to choose.

Deploy keys are bound to a version and nothing phones home

One paragraph in the README answers the question most licence text leaves open, which is what happens to the end user.

The PRO licences are developer licences. They are verified offline, explicitly described as involving no telemetry and no licence server. They allow royalty-free deployments to unlimited internal and external end-users and servers, with the stated intent of hassle-free management. Deployments use deploy keys that do not expire, and are instead bound to a specific version of xlwings.

That design has two consequences. There is no server to go down, and there is nothing for the vendor to learn about your usage, which is the same property the free Lite tier gets by being an add-in. In exchange, the key is coupled to a version rather than to a date, so upgrading xlwings is the moment at which the binding has to be revisited.

For a package embedded in a commercial workbook that customers download, this is the part that matters most, and it is stated in three sentences rather than in a table.

The version is regexed out of a source file and pytest is listed twice

Two small details in the packaging files are worth reading before you file anything against this project.

The first is the version. pyproject.toml declares `dynamic = ["version"]` and names no value. setup.py resolves it by opening `xlwings/__init__.py` and running a regular expression over the contents:

code
version = re.compile(r'.*__version__ = "(.*?)"', re.S).match(f.read()).group(1)

So the version of a published release is whatever that one line in the package's `__init__` says. The tagged releases are 0.37.5, 0.37.4 and 0.37.3, and the newest tag carries the same timestamp as the last push to main, so in practice the tag and the line move together.

The second is the `all` extra. It lists pytest twice, once between requests and pdfrw and again at the end after mistune. A duplicate in an extras list is harmless to a resolver, and it is the kind of artefact that a stricter packaging tool would flag as a warning.

The rest of the extras are consistent between pyproject.toml and setup.py, which is not guaranteed in a project that maintains both files.

Two ways to install into Excel, and they install different things

The question how do I install xlwings in Excel has two answers depending on which tier you want, and they are not variations of the same step.

The Python library is a normal package install. It gives you the scripting and macro surface: automating Excel from Python with a syntax close to VBA, replacing VBA macros with Python, and, on Windows only, writing user defined functions in Python. Numpy arrays and Pandas Series and DataFrames are supported, and the README states that xlwings-powered workbooks are easy to distribute and work on Windows and macOS.

The add-in is a different artefact. xlwings Lite is installed from Excel's own add-in store, and its selling point is that no local Python installation is required. It runs on Windows, macOS and Excel on the web, including the free version of Excel, and it keeps the Python code inside the workbook rather than beside it.

PRO is a third thing again, and the server component in it is the one that reaches furthest: no local Python, Excel on the web plus Google Sheets, integration with VBA, Office Scripts and Office.js, and custom functions on all platforms. That component lives in its own repository, xlwings-server.

So a team saying they use xlwings has said almost nothing until they say which of the three they mean.

Editorial conclusion

xlwings is the right tool when the workbook itself has to call your Python, because the open source tier covers scripting, macros and, on Windows, user defined functions. It is the wrong tool for reading spreadsheets on a server, since the Rust reader exists but a headless read path is a PRO feature. Before you depend on it, check which of the three tiers you are actually using, because they are licensed differently and two of them are not this package. And if you build it yourself, read the setup.py and Cargo.toml pair rather than assuming a normal Python build.

Frequently asked questions

How do I install xlwings using pip?

As an ordinary Python package, requiring Python 3.11 or later. Its only dependencies are pywin32 on Windows and psutil plus appscript on macOS, both marked by platform, so a Linux install pulls nothing.

how to install xlwings lite

xlwings Lite is installed from Excel's add-in store rather than from a package index. It requires no local Python, runs on Windows, macOS and Excel on the web including the free version, and stores the Python code inside the workbook.

What licence applies to xlwings?

The open source library is BSD 3-clause, declared in the package metadata and named in the README, with LICENSE.txt at the root. xlwings PRO is a separate, source-available tier dual-licensed under PolyForm Noncommercial or the PRO licence, with LICENSE_PRO.txt beside it.

How is xlwings built?

Through maturin with a Rust cdylib for most platforms, and through setup.py on Windows, because the DLLs are distributed as data_files. Cargo.toml pins calamine to a commit in a fork, and abi3 wheels are not supported since DateTime is outside the ABI spec.

Does xlwings PRO check in with a licence server?

No. The PRO licences are developer licences verified offline, with no telemetry and no licence server involved. Deployments use deploy keys that do not expire but are bound to a specific version of xlwings, and cover unlimited internal and external end-users.

Official sources

  1. Issues
  2. Project website
  3. README
  4. Releases
  5. xlwings/xlwings on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/xlwings-xlwings.svg)](https://hysenlabs.com/projects/xlwings-xlwings)