Choosing Between Source Distributions and Wheels for PyPI Publishing
Learn how to choose between Source Distributions (sdist) and Binary Wheels for PyPI. This guide compares installation speed, compatibility, and the manylinux standard to help you implement a hybrid publishing strategy.
27 Mar 2026, 15:23 UTC

The Distribution Dilemma: sdist vs. Wheel
When publishing a Python package to PyPI, you must decide how to package your code. Choosing only one format often leads to either installation failures for users lacking compilers or slow installation times for everyone. The goal is to balance maximum compatibility with a frictionless installation experience.
The core problem is the "build step." If a user installs a package that requires C extensions or complex configuration, their machine must compile that code. If they lack the necessary toolchain (like GCC or Clang), the installation fails. Binary wheels solve this by shifting the compilation burden from the user to the developer.
Comparing Distribution Formats
| Feature | Source Distribution (sdist) | Binary Wheel (bdist_wheel) |
|---|---|---|
| Contents | Raw source code + build metadata | Compiled bytecode/binaries + metadata |
| Install Speed | Slow (requires build step) | Fast (simple unpacking) |
| Client Requirements | Compiler, system headers, build tools | Python interpreter only |
| Portability | Universal (builds on any system) | Platform-specific (OS/Arch/Python version) |
| Maintenance | Low (one file for all) | High (multiple files for different OS/Arch) |
Engineering Trade-offs
The Case for sdist: An sdist is a mandatory safety net. Because it contains the raw source, it can be built on any architecture you didn't specifically target with a wheel. If you only provide wheels and a user is on an obscure Linux distro or a new ARM chip, pip will fail because there is no compatible binary.
The Case for Wheels: Wheels are essential for any package containing C, C++, or Rust extensions. Forcing users to compile these locally is a common point of failure in CI/CD pipelines and local development environments. For pure-Python packages, wheels still provide a performance boost by skipping the execution of setup.py or pyproject.toml build hooks.
The Manylinux Standard: For Linux wheels, you cannot simply build on Ubuntu and expect it to work on CentOS. The manylinux standard ensures portability by compiling against an older version of glibc (the GNU C Library), ensuring the binary runs on almost any modern Linux distribution.
Implementation Strategy: Hybrid Publishing
The industry standard is to publish both. This provides the speed of wheels for common platforms and the compatibility of sdist as a fallback.
To build both formats using the modern build frontend (assuming a pyproject.toml is present), run the following command in your project root:
# Install the build tool
pip install build
# Generate both sdist and wheel in the /dist folder
python -m build
Permissions: Run this as a standard user. Do not run as root/sudo to avoid permission issues with the generated dist/ directory.
Expected Result: You will see two files in the /dist folder: a .tar.gz file (the sdist) and a .whl file (the wheel).
Validating the Distribution
To ensure your package is truly portable and that the sdist is functional, you should test the installation without using the cached binary.
Run this command in a clean virtual environment to force pip to ignore the wheel and build from the source distribution:
# Replace with your actual package
pip install --no-binary :all:
Diagnostic Checks:
- If the installation succeeds, your sdist is correctly configured with all necessary build dependencies.
- If it fails with a "command 'gcc' failed" error, you have a missing system dependency that must be documented for users who cannot use your wheels.
- To see which wheel tags your current system supports, run
pip debugand look for theCompatible tagssection.
Limitations and Risks
Binary wheels for C extensions must be built for every target combination (e.g., Windows x86_64, macOS arm64, Linux x86_64). If you upload a wheel tagged for cp310 (Python 3.10), users on Python 3.11 will be forced to use the sdist, potentially triggering the build failures mentioned above.
Rollback: If you upload an incorrect wheel to PyPI, you cannot "overwrite" the file. You must use twine to yank the specific version: twine yank --.whl. This prevents new users from installing the broken binary while allowing existing users to keep it.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.