What is setup.py?
Categories:
Understanding setup.py: The Heart of Python Package Distribution

Explore setup.py, its role in Python packaging, how it defines metadata, dependencies, and entry points for your projects, and its evolution in the Python ecosystem.
In the world of Python, sharing your code with others or deploying it to production environments often involves packaging. At the core of traditional Python packaging lies setup.py
, a script that serves as the build script for your project. It's the primary way to define how your Python package is built, distributed, and installed. While newer tools and standards like pyproject.toml
are gaining prominence, understanding setup.py
remains crucial for working with many existing Python projects and grasping the fundamentals of Python packaging.
What is setup.py?
setup.py
is a Python script that lives in the root directory of your project. It uses the setuptools
library (which extends the older distutils
) to describe your project's metadata and how it should be packaged. When you run commands like python setup.py install
or python setup.py sdist
, this script is executed to perform the packaging operations.
flowchart TD A[Developer's Project] --> B{setup.py} B --> C[Metadata (Name, Version, Author)] B --> D[Dependencies (install_requires)] B --> E[Package Data (include_package_data)] B --> F[Entry Points (console_scripts)] B --> G[Build Commands (sdist, bdist_wheel)] G --> H[Distributable Package (e.g., .whl, .tar.gz)] H --> I[PyPI / Local Installation]
The role of setup.py in the Python packaging workflow.
The main function within setup.py
is setup()
, which takes various keyword arguments to define the package's characteristics. These arguments include essential information like the package name, version, author, description, and most importantly, its dependencies and the files it contains.
from setuptools import setup, find_packages
setup(
name='my_awesome_package',
version='0.1.0',
author='Your Name',
author_email='your.email@example.com',
description='A short description of my awesome package.',
long_description=open('README.md').read(),
long_description_content_type='text/markdown',
url='https://github.com/yourusername/my_awesome_package',
packages=find_packages(),
install_requires=[
'requests>=2.25.1',
'beautifulsoup4>=4.9.3',
],
classifiers=[
'Programming Language :: Python :: 3',
'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent',
],
python_requires='>=3.7',
entry_points={
'console_scripts': [
'my-cli-tool=my_awesome_package.cli:main',
],
},
include_package_data=True,
)
A typical setup.py
file demonstrating common arguments.
Key Arguments and Their Purpose
The setup()
function accepts numerous arguments, each serving a specific purpose in defining your package. Understanding these is key to creating a well-formed and easily distributable Python project.
name
: The name of your package. This is how users will refer to it (e.g.,pip install my_awesome_package
).version
: The current version of your package (e.g.,0.1.0
). Following semantic versioning is a good practice.author
,author_email
: Contact information for the package author.description
,long_description
,long_description_content_type
: Short and long descriptions of your package, often read fromREADME.md
.url
: The project's homepage or repository URL.packages
: A list of Python packages (directories containing__init__.py
files) to include.find_packages()
is a convenient helper function fromsetuptools
.install_requires
: A list of strings specifying the project's runtime dependencies.setuptools
will ensure these are installed when your package is installed.classifiers
: A list of strings that categorize your project for PyPI, helping users find it.python_requires
: Specifies the Python versions your package is compatible with.entry_points
: Defines console scripts or GUI entry points, allowing users to run commands directly from your installed package.include_package_data
: IfTrue
,setuptools
will look for aMANIFEST.in
file to include non-Python files (like data files, templates, etc.) in your distribution.
requests>=2.25.1
) to ensure compatibility and prevent unexpected breakage from future dependency updates.Evolution and Alternatives: pyproject.toml
While setup.py
has been the standard for a long time, the Python packaging landscape is evolving. The introduction of pyproject.toml
(defined by PEP 518 and PEP 621) aims to centralize build system configuration and package metadata in a single, static file. Tools like Poetry
and Flit
leverage pyproject.toml
extensively, and setuptools
itself now supports defining metadata directly within pyproject.toml
.
For new projects, especially those not requiring complex build logic, using pyproject.toml
for metadata and relying on build backends like setuptools
or hatch
is often recommended. However, setup.py
still offers flexibility for more intricate build processes, custom commands, or when dealing with older projects.
graph TD A[Project Configuration] --> B{Traditional setup.py} A --> C{Modern pyproject.toml} B --> D[Dynamic Metadata] B --> E[Custom Build Logic] C --> F[Static Metadata] C --> G[Build System Backend (e.g., setuptools, poetry)] D --> H[Flexibility] E --> H F --> I[Simplicity] G --> I
Comparison of setup.py and pyproject.toml approaches.
pyproject.toml
for metadata, setuptools
might still be the underlying build backend, and a minimal setup.py
might be present for backward compatibility or specific build steps.Common setup.py Commands
Here are some frequently used commands executed with setup.py
:
1. Install in editable mode
This command installs your package in 'editable' or 'development' mode. Changes to your source code are immediately reflected without re-installation.
pip install -e .
2. Create a source distribution
This command creates a source distribution (sdist), typically a .tar.gz
file, containing your source code and any data files specified in MANIFEST.in
.
python setup.py sdist
3. Create a wheel distribution
This command creates a wheel distribution (.whl
file), which is a pre-built distribution format that can be installed without needing to run setup.py
during installation, making it faster and more reliable.
python setup.py bdist_wheel
4. Upload to PyPI
After creating distributions, you can upload them to PyPI (the Python Package Index) using twine
.
twine upload dist/*