Python tutorials > Modules and Packages > Packages > How to distribute packages?
How to distribute packages?
Distributing your Python packages allows others to easily install and use your code. This tutorial covers the steps required to package and distribute your Python project using modern tools like setuptools
and wheel
, and upload it to the Python Package Index (PyPI).
Project Structure
Before packaging, organize your project with a clear structure. A typical project looks like this:
my_package/
├── my_module.py
├── __init__.py
├── data/
│ └── my_data.txt
├── tests/
│ ├── test_my_module.py
│ └── __init__.py
├── LICENSE
├── README.md
└── setup.py
my_package/
is the root directory of your package. my_module.py
contains your code. __init__.py
makes the directory a Python package. data/
stores non-code data files. tests/
contains your tests. LICENSE
specifies the license. README.md
provides project information. setup.py
is crucial; it describes your package for installation.
setup.py: Defining Your Package
The setup.py
file is the heart of your distribution process. Let's break it down:
name
: The name of your package (must be unique on PyPI).version
: A version number following semantic versioning (e.g., 0.1.0).author
/author_email
: Your contact information.description
: A brief summary of your package.long_description
: A detailed description, often read from your README.md
file. Using long_description_content_type='text/markdown'
tells setuptools
to render the Markdown.url
: The URL of your project's homepage (e.g., a GitHub repository).packages=find_packages()
: Automatically discovers all packages in your project (directories with __init__.py
).classifiers
: Metadata tags to help users find your package on PyPI. See PyPI's list of classifiers.python_requires
: Specifies the minimum Python version your package supports.install_requires
: A list of dependencies that will be installed when your package is installed.package_data
: Specifies non-code files to include in your package. In this example, all files in the my_package/data
directory.include_package_data
: If True
, setuptools
will automatically include files matched by version control (e.g., Git) and specified in MANIFEST.in
(more on that below).
from setuptools import setup, find_packages
with open('README.md', 'r') as f:
long_description = f.read()
setup(
name='my_package',
version='0.1.0',
author='Your Name',
author_email='your.email@example.com',
description='A short description of your package',
long_description=long_description,
long_description_content_type='text/markdown',
url='https://github.com/yourusername/my_package',
packages=find_packages(),
classifiers=[
'Programming Language :: Python :: 3',
'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent',
],
python_requires='>=3.6',
install_requires=[
'requests',
],
package_data={'my_package': ['data/*']},
include_package_data=True
)
MANIFEST.in: Including Additional Files
The MANIFEST.in
file is used when include_package_data=True
in setup.py
. It specifies additional files to include in your package distribution that might not be automatically included by setuptools
. Common use cases include LICENSE
, README.md
, and data files.
include LICENSE
and include README.md
: Explicitly include these files.recursive-include my_package/data *
: Recursively include all files in the my_package/data
directory.
include LICENSE
include README.md
recursive-include my_package/data *
Building the Distribution Packages
Use the following command in your project's root directory (where The resulting distribution files will be placed in the setup.py
is located) to build the distribution packages:python setup.py sdist bdist_wheel
sdist
: Creates a source distribution (.tar.gz
) containing your code and metadata.bdist_wheel
: Creates a wheel distribution (.whl
), a binary package format that is faster to install.dist/
directory.
python setup.py sdist bdist_wheel
Installing twine
twine
is a secure tool for uploading your packages to PyPI. Install it using pip:pip install twine
pip install twine
Uploading to PyPI
Use You will be prompted for your PyPI username and password. It's strongly recommended to use an API token for increased security. You can generate API tokens on the PyPI website (Account settings -> API tokens). Test PyPI: Before uploading to the main PyPI, it's good practice to upload to Test PyPI to verify your package works as expected. Use the following command: And install from Test PyPI using:twine
to upload your distribution packages to PyPI:twine upload dist/*
twine upload --repository testpypi dist/*
pip install --index-url https://test.pypi.org/simple/ my_package
twine upload dist/*
Concepts Behind the Snippet
The core concept revolves around standardizing the packaging and distribution process. setuptools
provides the framework for defining the package metadata and dependencies, while wheel
creates optimized installation packages. twine
ensures secure uploading to PyPI. The project structure and MANIFEST.in
guarantee all necessary files are included.
Real-Life Use Case Section
Imagine you've built a Python library for interacting with a specific API. You want other developers to easily use your library in their projects. By packaging and distributing your library on PyPI, they can simply install it using pip install my_api_library
, making your code accessible and reusable.
Best Practices
Interview Tip
When discussing package distribution in an interview, emphasize the importance of code reusability, maintainability, and collaboration. Highlight your understanding of setuptools
, wheel
, twine
, and the overall process. Be prepared to explain the purpose of setup.py
and MANIFEST.in
, and the benefits of using API tokens for secure uploads.
When to Use Them
Use this process whenever you want to share your Python code with others, whether it's within your organization or publicly on PyPI. It's especially beneficial for libraries, tools, and applications that are intended for reuse.
Alternatives
While setuptools
is the most common approach, other packaging tools exist, such as:
pyproject.toml
file.
Pros
Cons
FAQ
-
What is an API token and why should I use it?
An API token is a secure alternative to your PyPI username and password for uploading packages. It limits the scope of access and prevents your primary credentials from being compromised if the token is leaked. You can generate API tokens in your PyPI account settings.
-
How do I update my package after making changes?
Increase the
version
number in yoursetup.py
file (following semantic versioning). Rebuild the distribution packages usingpython setup.py sdist bdist_wheel
and upload them to PyPI usingtwine upload dist/*
. -
My package has native extensions. How do I distribute it?
Building and distributing packages with native extensions requires extra care. Consider using tools like
cibuildwheel
to build wheels for different platforms and Python versions. Refer to thesetuptools
documentation for details on handling native extensions.