NeuroAgent

Complete Guide to setup.py for Python Package Development

Learn what setup.py is and how to configure it for Python package development. Complete guide covering basic to advanced configuration, project structure, and modern alternatives.

Question

What is setup.py and how can it be configured or used for Python package development?

NeuroAgent

setup.py is a Python script that serves as the standard configuration file for defining package metadata, dependencies, and build instructions in Python package development. It enables developers to specify essential information about their package such as name, version, author details, and requirements, while providing commands for building and distributing packages to PyPI. The file works in conjunction with setuptools to automate the packaging process, making it easier to share and install Python code across different environments.

Contents

Understanding setup.py

setup.py is a fundamental component in Python package development that acts as the central configuration file for defining how a package should be built, what its metadata contains, and how it should be distributed. According to VPK Technologies, setup.py is “the standard way to define metadata about your package and its dependencies.”

The primary purpose of setup.py is to provide setuptools (the Python packaging library) with all the information needed to:

  • Discover and package Python modules
  • Define package dependencies
  • Generate distribution archives
  • Handle installation requirements
  • Set up entry points for command-line tools

As explained in the Xebia guide, the setup.py file essentially serves as the “control center” for your Python package, orchestrating the entire packaging and distribution process.

Basic setup.py Configuration

A minimal setup.py file follows a standard structure using setuptools. Here’s the basic configuration template:

python
from setuptools import setup, find_packages

VERSION = '0.0.1'
DESCRIPTION = 'My first Python package'
LONG_DESCRIPTION = 'My first Python package with a slightly longer description'

setup(
    name="verysimplemodule",
    version=VERSION,
    author="Your Name",
    author_email="<youremail@email.com>",
    description=DESCRIPTION,
    long_description=LONG_DESCRIPTION,
    packages=find_packages(),
    install_requires=[]
)

Key Basic Parameters:

  • name: The package name, which must match the folder name
  • version: Package version number (typically following semantic versioning)
  • author: Author’s name
  • author_email: Author’s email address
  • description: Short description of the package
  • long_description: Detailed description
  • packages: Automatically discovers all packages using find_packages()
  • install_requires: List of dependencies that need to be installed with the package

As shown in the freeCodeCamp tutorial, this basic configuration is sufficient for most simple Python packages you might build.

Advanced Configuration Options

For more comprehensive package management, setup.py supports numerous additional parameters:

python
setup(
    name="my_package",
    version="1.0.0",
    author="Your Name",
    author_email="email@example.com",
    description="A comprehensive Python package",
    long_description=open("README.md").read(),
    long_description_content_type="text/markdown",
    url="https://github.com/username/my_package",
    packages=find_packages(),
    classifiers=[
        "Development Status :: 5 - Production/Stable",
        "Intended Audience :: Developers",
        "License :: OSI Approved :: MIT License",
        "Programming Language :: Python :: 3",
        "Programming Language :: Python :: 3.8",
        "Programming Language :: Python :: 3.9",
        "Programming Language :: Python :: 3.10",
        "Programming Language :: Python :: 3.11",
    ],
    python_requires=">=3.8",
    install_requires=[
        "requests>=2.25.1",
        "numpy>=1.21.0",
        "pandas>=1.3.0",
    ],
    extras_require={
        "dev": ["pytest>=6.0", "black", "flake8"],
        "docs": ["sphinx", "sphinx-rtd-theme"],
    },
    entry_points={
        "console_scripts": [
            "my-package=my_package.cli:main",
        ],
    },
    include_package_data=True,
    zip_safe=False,
)

Key Advanced Parameters:

  • classifiers: PyPI classifiers that help categorize your package
  • python_requires: Minimum Python version requirement
  • extras_require: Optional dependencies for different use cases
  • entry_points: Defines command-line tools and plugins
  • include_package_data: Include non-Python files specified in MANIFEST.in
  • url: Project homepage or repository URL
  • long_description_content_type: Format of the long description

Project Structure Requirements

For setup.py to work correctly, your project must follow a specific directory structure. According to GeeksforGeeks, you need to:

  1. Create a package folder with an __init__.py file inside it
  2. Ensure proper organization of your Python modules
  3. Follow naming conventions that align with your setup.py configuration

The typical project structure looks like:

my_project/
├── setup.py
├── README.md
├── MANIFEST.in
├── my_package/
│   ├── __init__.py
│   ├── module1.py
│   ├── module2.py
│   └── subpackage/
│       ├── __init__.py
│       └── utils.py
├── tests/
│   ├── __init__.py
│   └── test_module1.py
└── docs/
    └── source/
        ├── conf.py
        └── index.rst

Key structural requirements:

  • Package folder: Must contain __init__.py (even if empty)
  • setup.py location: Should be in the project root directory
  • README.md: Typically referenced in setup.py for long description
  • MANIFEST.in: Specifies additional files to include in the distribution

Important: The __init__.py file is what makes a directory a Python package. It can be empty or contain package initialization code, but it must be present for find_packages() to discover your modules.

Modern Alternatives to setup.py

While setup.py has been the traditional standard, Python packaging is evolving toward more modern approaches. As noted in the Xebia updated guide, “the recommended way of using Setuptools has shifted in the direction of using the Pyproject.toml in favour of setup.py and setup.cfg.”

pyproject.toml

The modern alternative is pyproject.toml, which serves as “a single source of truth for project metadata” according to PyDevTools.

Here’s a minimal pyproject.toml example:

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

[project]
name = "mypkg"
description = "really awesome package."
keywords = ["random", "cool"]
classifiers = [
    "Development Status :: 5 - Production/Stable",
    "Environment :: Console",
    "Intended Audience :: Science/Research",
    "Operating System :: OS Independent",
    "Programming Language :: Python :: 3",
]
requires-python = ">=3.7"
dynamic = ["version", "readme"]

[tool.setuptools.dynamic]
readme = {file = ["README.md"], content-type = "text/markdown"}
version = {attr = "mypkg.__version__"}

[project.optional-dependencies]
dev = ["pytest>=6.0", "black", "flake8"]
docs = ["sphinx", "sphinx-rtd-theme"]

Key Benefits of pyproject.toml:

  • PEP compliance: Follows modern packaging standards (PEP-517, PEP-518, PEP-621)
  • Single configuration: Consolidates metadata that was spread across multiple files
  • Better tooling support: Native support in modern Python build tools
  • Static analysis: Easier for tools to parse and validate configuration

When to Use setup.py vs pyproject.toml:

Scenario Recommended Approach
New projects pyproject.toml
Legacy projects Gradually migrate to pyproject.toml
Complex build systems pyproject.toml with custom build backend
Simple internal packages setup.py (for simplicity)
Projects requiring wide compatibility setup.py (maximum compatibility)

Note: According to Ian Hopkinson, as of May 2023, “project settings formerly in setup.cfg can now go in pyproject.toml, as per PEP-621.”

Building and Distributing Packages

Once your setup.py is configured, you can use it to build and distribute your Python package. The process involves several key commands:

Basic Build Commands

  1. Build source distribution:

    bash
    python setup.py sdist
    
  2. Build wheel distribution (recommended):

    bash
    python setup.py bdist_wheel
    
  3. Build both formats:

    bash
    python setup.py sdist bdist_wheel
    

Upload to PyPI

To publish your package to the Python Package Index (PyPI):

bash
python setup.py sdist upload -r pypi

However, the modern approach is to use twine for more secure uploads:

bash
# First build your distributions
python setup.py sdist bdist_wheel

# Then upload with twine
twine upload dist/*

Installation Options

setup.py also enables different installation modes:

  1. Standard installation:

    bash
    pip install .
    
  2. Editable installation (development mode):

    bash
    pip install -e .
    

    As mentioned in the Ian Hopkinson guide, editable installation means “changes in the code will be immediately reflected in the functionality of the package.”

  3. Installation with extras:

    bash
    pip install .[dev,docs]
    

Best Practice: Always use virtual environments when working with Python packages to avoid dependency conflicts. As recommended by Xebia, “It is common and recommended practice to use virtual environments for work in Python.”

Best Practices and Migration

When working with setup.py, several best practices should be followed to ensure maintainable and future-proof packaging:

Current Best Practices

  1. Use version control: Keep your setup.py in version control alongside your package code
  2. Automate builds: Use CI/CD pipelines to automatically build and test packages
  3. Document dependencies: Keep requirements.txt for development alongside setup.py
  4. Test thoroughly: Use tools like tox to test across multiple Python versions
  5. Follow semantic versioning: Use meaningful version numbers that reflect changes

Migration to Modern Standards

For projects currently using setup.py, consider migrating to pyproject.toml:

  1. Start simple: Begin with basic pyproject.toml configuration
  2. Gradual migration: Move configuration piece by piece
  3. Maintain compatibility: Keep setup.py during transition if needed
  4. Update tooling: Modernize your build and deployment pipeline
  5. Test thoroughly: Ensure all functionality works with the new configuration

Future Considerations

As Python packaging continues to evolve, consider these future trends:

  • PEP 621: Standard metadata specification for pyproject.toml
  • Build backends: Moving beyond setuptools for specialized build needs
  • Dependency resolution: Improved dependency management tools
  • Security enhancements: Better signing and verification mechanisms

According to PyDevTools, “Setuptools can be configured through pyproject.toml or the legacy setup.py file,” indicating that both approaches will remain supported for the foreseeable future.

Conclusion

setup.py remains a fundamental tool in Python package development, serving as the traditional configuration file that defines package metadata, dependencies, and build instructions. While newer alternatives like pyproject.toml are gaining prominence, understanding setup.py is still essential for working with existing Python packages and maintaining compatibility across different environments.

Key takeaways include:

  • setup.py works with setuptools to automate packaging and distribution
  • It uses parameters like name, version, author, and dependencies to define package metadata
  • Project structure requirements include proper package organization with init.py files
  • Modern alternatives like pyproject.toml offer improved configuration management
  • Building and distributing packages involves commands like python setup.py sdist and twine upload
  • Virtual environments are recommended for all package development work

As Python packaging continues to evolve, developers should stay informed about new standards and best practices while maintaining the skills to work with both traditional and modern packaging approaches.

Sources

  1. A Practical Guide To Using Setup.py | Xebia
  2. How to Build Your Very First Python Package | freeCodeCamp
  3. What is setup.py in Python? | GeeksforGeeks
  4. Understanding setup.py, setup.cfg and pyproject.toml in Python | SomeBeans
  5. How to Create Python Package with setup.py | VPK Technologies
  6. A Practical Guide To Setuptools And Pyproject.toml | Xebia
  7. An Updated Guide To Setuptools And Pyproject.toml | Xebia
  8. setuptools – Python Developer Tooling Handbook
  9. Why Should I Choose pyproject.toml over requirements.txt? | PyDevTools
  10. Python minimal package with pyproject.toml | Scientific Computing