Skip to Content
Course content

346: Understanding sdist vs Wheel Distribution Formats

Click on the "Edit" button in the top corner of the screen to edit your slide content.

If you've spent any time browsing PyPI or looking at the files inside your site-packages folder, you've probably noticed two very different types of files: those ending in .tar.gz and those ending in .whl. To the uninitiated, they both just seem like "the package," but they represent two completely different philosophies of delivery.

The IKEA approach to Python packages

Think of an sdist (Source Distribution) as an IKEA flat-pack box. When you buy a bookshelf this way, IKEA sends you a box containing raw pieces of wood, a bag of screws, and a set of instructions. The bookshelf doesn't "exist" yet; it's just the potential for a bookshelf. To actually use it, you have to spend an hour in your living room with a screwdriver, putting it all together. If you don't have a screwdriver (a compiler), you're stuck.

A Wheel, on the other hand, is like having that same bookshelf delivered fully assembled by a professional crew. They carry it through the door and set it exactly where you want it. You don't need tools, you don't need to read instructions, and it's ready for books the second it hits the floor.

Here is how that maps directly to Python:

  • The Flat-pack Box = sdist: This is a archive of your source code. It contains your pyproject.toml, your setup.py, and all your .py files.
  • The Assembly Process = Building: When you pip install an sdist, Python has to "build" it. If the package includes C extensions (like numpy or cryptography), your computer actually has to run a C compiler to turn that source code into machine code.
  • The Assembled Furniture = Wheel: This is a "built distribution." The compilation has already happened on the developer's machine. The Wheel is essentially a ZIP file with a specific filename that tells pip exactly where the files belong on your system.

Why the sdist still matters

You might be wondering why we bother with sdists at all. Why not just ship Wheels? Well, Wheels are often platform-specific. A Wheel built for Windows won't work on a Raspberry Pi running Linux because the compiled binary code is different. I've seen plenty of developers get frustrated when a package fails to install on a niche Linux distro—usually, it's because there wasn't a pre-built Wheel for that specific architecture, and the sdist build failed because the user was missing a required system header file.

The sdist is the "universal backup." It's the raw truth of the code. If a Wheel doesn't exist for your weird OS, pip will fall back to the sdist and try to build it from scratch on your machine. It's slower and more prone to errors, but it's the only way to ensure the code can run anywhere.

The "Wheel" advantage in production

In a professional CI/CD pipeline, you almost always want to use Wheels. Imagine you have a production server that needs to scale up rapidly. If you use sdists, every new server instance has to spend three minutes compiling pandas before the app can even start. That's a nightmare.

By using Wheels, the installation is just a matter of moving files from one folder to another. It's nearly instantaneous. When I'm configuring Dockerfiles for my teams, I always make sure we're installing cached Wheels rather than rebuilding from source. It turns a 10-minute deployment into a 30-second one.

# What happens under the hood when you run:
# pip install some_package

# 1. pip looks for a Wheel (.whl) that matches your OS and Python version.
# 2. If found, it just unzips it into site-packages. (FAST)
# 3. If not found, it looks for an sdist (.tar.gz).
# 4. If found, it runs the build process (often calling 'setuptools' or 'flit'). (SLOW)
# 5. If that build fails (e.g., missing gcc compiler), you get a massive red error block.



📋 Practical Task

Building and Comparing sdist and Wheel Artifacts for a Custom Utility

To truly understand the difference, you need to see what's inside these archives. In this exercise, you will create a tiny package, build both distribution formats, and inspect their contents.

Requirements: You will need the build package installed (pip install build).

  1. Create a directory named dist_test and inside it, create a folder named my_utility.
  2. Inside my_utility, create an empty __init__.py and a file named core.py with a simple function: def hello(): print("Hello from the wheel!").
  3. In the root dist_test folder, create a pyproject.toml file with the following minimal content:
    [build-system]
    requires = ["setuptools", "wheel"]
    build-backend = "setuptools.build_meta"
    
    [project]
    name = "my_utility"
    version = "0.1.0"
    
  4. Run the build command from the dist_test directory: python -m build.
  5. Look inside the newly created dist/ folder. You will see a .tar.gz file and a .whl file.
  6. The Investigation:
    • Open the .tar.gz file (using a zip tool or tar -tf). Notice how it contains the pyproject.toml and the raw source structure.
    • Open the .whl file. Notice that the pyproject.toml is gone, and you have a .dist-info folder containing metadata. The .whl is essentially a "ready-to-install" snapshot.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.