Choosing Between sdist and Wheels for PyPI Distribution
Learn when to use Source Distributions (sdist) versus Wheels (.whl) for PyPI packages to balance installation speed and cross-platform compatibility.
28 Mar 2026, 14:36 UTC

The Distribution Dilemma: Build Speed vs. Compatibility
When publishing a Python package to PyPI, you must decide whether to distribute your code as a Source Distribution (sdist), a Built Distribution (wheel), or both. The wrong choice often results in "failed to build wheel" errors for your users, typically caused by missing C compilers or system headers on the end-user's machine.
The primary takeaway: Always provide both an sdist and a wheel. The wheel ensures fast, reliable installation for the majority of users, while the sdist acts as a safety net for niche architectures and allows for source auditing.
Comparing Distribution Formats
| Feature | Source Distribution (sdist) | Built Distribution (Wheel) |
|---|---|---|
| Format | .tar.gz |
.whl |
| Install Speed | Slower (requires build step) | Fast (direct unpack) |
| Dependencies | Requires build tools (setuptools, compilers) | Requires only pip |
| Portability | Universal (builds on target) | Platform-specific (OS/Arch) |
| C Extensions | User must compile locally | Pre-compiled by maintainer |
Evaluating Trade-offs
The sdist-only approach is the simplest for the maintainer. You upload one file, and the user's machine handles the heavy lifting. However, if your project contains C, C++, or Rust extensions, this forces every user to install a full build chain (like GCC or MSVC), which is a significant barrier to entry and a common cause of installation failure in CI/CD pipelines.
The wheel-only approach is risky. Wheels are tagged by platform (e.g., manylinux2014_x86_64). If a user is on an unsupported architecture (like a specific ARM build or a new macOS version), pip will find no matching wheel and will fail immediately because there is no source code to fall back on.
The Hybrid approach is the industry standard. When a user runs pip install, pip looks for a compatible wheel first. If one exists, it installs instantly. If no compatible wheel is found, it downloads the sdist and attempts to build a wheel locally.
Implementation: Building and Validating Distributions
Assuming you are using a modern pyproject.toml setup with build, follow these steps to generate both formats.
1. Generate the distributions
Run this command in your project root. This requires the build package (pip install build).
python -m build
Expected Result: Two files will be created in the /dist directory: a .tar.gz (sdist) and a .whl (wheel).
2. Validate metadata
Before uploading, use twine to ensure the metadata is compliant with PyPI standards. Run this from your terminal with the twine package installed.
twine check dist/*
Risk: If twine check fails, your package may be uploaded but will be unsearchable or fail to install due to malformed metadata.
3. Verify the installation behavior
To confirm which format pip is choosing, install your package in a clean virtual environment using the verbose flag:
pip install . --verbose
Look for lines indicating Using cached ... .whl (indicating a wheel install) or Running setup.py install / Building wheel... (indicating an sdist fallback).
Limitations and Constraints
- Binary Compatibility: If you provide wheels for C extensions, you cannot simply build them on your local machine and upload them. You must use a tool like
cibuildwheelto build across multiple OS versions (e.g., using manylinux Docker images) to ensure they work on other users' systems. - Wheel Tagging: Incorrect tags (e.g., marking a pure-python wheel as platform-specific) can prevent
pipfrom downloading the package on compatible systems.
Rollback Procedure
If you upload a corrupted wheel or an sdist with a critical bug, you can remove the specific release version from PyPI using twine or the PyPI web interface. Note that this does not remove the version from users who have already installed it; you must upload a new, patched version (e.g., incrementing from 1.0.0 to 1.0.1).
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.