Fix Python setup.py bdist_wheel did not Run Successfully.

When packaging Python projects into wheel distributions, you may see this error:

running bdist_wheel
error: bdist_wheel did not run successfully.
exit code: 1

This occurs when something goes wrong while running the bdist_wheel command to build a wheel file.

In this comprehensive guide, I’ll explain what causes this error and how to troubleshoot and fix wheel building failures in Python.

Let’s start by understanding how Python wheels work and why building them can fail.

Background on Python Wheels

Python wheels are a built package format that provides pre-compiled binary distributions for a Python project.

Wheels contain all of a project’s files and metadata in a compressed archive that can be installed with pip.

Wheels aim to replace eggs as the standard distribution format for Python packages. They provide advantages like:

  • Faster installation compared to source distributions
  • Built once and cached natively by pip
  • Contain compiled Python extensions ready to use
  • More consistent naming convention than eggs

Under the hood, the bdist_wheel command invoked via setup.py or python setup.py handles building wheels.

When bdist_wheel fails, it means this wheel building process encountered an error.

Understanding setup.py and bdist_wheel

The setup.py file contains metadata and build configuration for packaging Python projects.

When you run:

python setup.py bdist_wheel

This invokes the bdist_wheel command defined in setuptools.

The bdist_wheel command does work like:

  • Gathering project metadata from setup.py
  • Building any C/C++ extension modules for wheels
  • Compressing project files into a .whl wheel archive

If any of these steps fail, bdist_wheel exits with an error code signaling the failure.

Now let’s look at some specific reasons bdist_wheel may not complete successfully.

Origins of the Error

There are a few common causes of bdist_wheel failures:

  • Missing build dependencies and compilers to build extension modules
  • Python version incompatibilities between interpreter and project
  • Platform-specific issues building wheels on certain OSes
  • Invalid setup.py syntax errors
  • Problems compiling C extensions
  • Bugs in a project’s wheel build logic

The error is generic so you need to troubleshoot to find the specific cause.

Checking setup.py Contents

Examine the project’s setup.py file for any potential issues:

  • Verify syntax is valid Python without errors
  • Check for a platforms argument that may prevent building on your OS
  • Ensure install_requires matches your Python version
  • Look for C extensions needing compilers or libraries

setup.py issues can prevent bdist_wheel from succeeding.

Installing Build Dependencies

If building C extensions, ensure you have build dependencies like:

  • Python developer headers
  • A C compiler like gcc or MSVC
  • Any required library development packages

On Linux:

sudo apt install python3-dev gcc libssl-dev

On Windows, Visual Studio Build Tools includes required compilers.

Install all expected build tools before rebuilding wheels.

Trying a Clean Build

Stale build artifacts can sometimes cause issues. Try a fresh build:

# Delete previous builds
rm -rf build dist

# Rebuild wheel 
python setup.py bdist_wheel

This ensures you start with a clean slate.

Checking Python Version Compatibility

Make sure the Python version you are building with matches what the project supports.

Inspect fields like:

  • python_requires in setup.py
  • classifiers Trove list
  • Any version checks in the code

Building against unsupported Python versions commonly triggers failures.

Testing on Multiple Platforms

Attempt wheel builds on different operating systems and Python versions:

  • Try on Linux, macOS, and Windows
  • Switch between Python 3.7, 3.8, 3.9, etc.

See if bdist_wheel only fails on certain configurations, which narrows down the issue.

Configuring C Compiler Options

For building extensions, you can configure the compiler flags in setup.py:

from setuptools import setup, Extension

ext_modules = [
    Extension(
        'package.module',
        extra_compile_args=['-O3', '-ffast-math'] 
    )
] 

setup(
    ...,
    ext_modules=ext_modules
)

Tune these to fix compile-time failures.

Creating a Setup.cfg File

setuptools offers a setup.cfg file for isolating build configuration:

[bdist_wheel]
universal = 1

This prevents cluttering setup.py with compile options.

Handling Extension Module Issues

For C extensions, troubleshoot issues like:

  • Missing headers or libraries
  • Incompatible module code
  • Compiler errors

The bdist_wheel process will surface these. Fix the native code first.

Fixing Syntax Errors

Of course, any syntax errors in setup.py will prevent running successfully:

# Missing colon 
ext_modules = [
    Extension(
        'package.module'
        extra_compile_args=['-O3', '-ffast-math']
    )
]

Run python setup.py bdist_wheel first to catch syntax issues.

Skipping bdist_wheel

As a workaround, you can skip wheel building by installing from an sdist or directory:

# Build source distribution instead  
python setup.py sdist

pip install ./dist/package-1.0.tar.gz

This allows installing even if bdist_wheel is broken.

Using pyproject.toml for Builds

The new pyproject.toml standard defines build dependencies and configuration instead of setup.py.

For example:

[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"

This can solve some setuptools issues.

Building with pip wheel

You can build wheels directly with pip instead of setup.py:

pip wheel .

This uses pip’s own wheel building logic, which sometimes works better.

Troubleshooting on Windows

On Windows, Visual Studio build tools are required for compiling extensions.

Errors like “MSVC is not installed” indicate these are missing.

Also try building wheels with CPython rather than WinPython for best results.

Diagnosing Encoding Problems

Check for ASCII encoding issues on non-English locale systems:

import locale
print(locale.getpreferredencoding())

Force UTF-8 if ASCII encoding is causing problems:

import sys
sys.setdefaultencoding('UTF8')

Looking for Log Files and Output

Check for verbose build output, generated log files, or stdout/stderr redirects to glean more details on the failure.

Piping to a log can help:

python setup.py bdist_wheel &> wheel.log

Reporting Bugs to Package Maintainers

If you are still unable to resolve wheel building failures, report bugs to the package developers providing:

  • Package name and version
  • Python version
  • pip version
  • OS and architecture
  • Full error callstack/logs/output
  • Steps attempted to resolve the issue

This helps maintainers identify flaws in the wheel building process.

Submitting Fixes to Python Projects

Consider submitting a pull request to the project’s codebase fixing any wheel building issues you identified.

Improvements to setup.py configuration, extension module code, build scripts and other areas of the packaging process can help the Python community.

Following Packaging Best Practices

Some tips for creating portable wheels:

  • Support Python 3.7+
  • Use setuptools rather than distutils
  • Declare OS and Python version compatibility
  • Include license files in distributions
  • Use manylinux CI builds for Linux wheels

Carefully following Python wheel packaging standards avoids many bdist_wheel errors.

Conclusion

bdist_wheel did not run successfully errors usually arise from configuration problems, build dependency issues, platform inconsistencies, or packaging bugs.

Thoroughly troubleshooting your environment, dependencies, Python versions, and wheel outputs can help identify the root cause.

Ensuring consistent and compatible build configurations across platforms is key to maintaining portable wheel distributions.

I hope these troubleshooting tips help you smooth out any wheel building problems! Please let me know if you have any other suggestions.

Leave a Comment