Backend Development 8 min read

How to Package and Publish a Python Project to PyPI

This tutorial explains why Python projects need packaging, introduces essential tools like setuptools, wheel, and twine, shows the recommended project layout, walks through creating a setup.py file, building distribution files, testing locally, uploading to PyPI, and handling version updates and common questions.

php中文网 Courses
php中文网 Courses
php中文网 Courses
How to Package and Publish a Python Project to PyPI

In Python development, writing code is only the first step; packaging and publishing the project to PyPI (or other repositories) enables easy installation for other developers. This guide covers the entire workflow.

1. Why package a Python project?

Convenient installation via pip install your-package

Automatic dependency management

Version control for users

Sharing code through PyPI or private repositories

2. Python packaging tools

The official toolchain uses setuptools for packaging, combined with wheel to generate binary distribution files. The table below summarizes the main tools:

Tool

Purpose

setuptools

Define project metadata, dependencies, entry points, etc.

wheel

Generate

.whl

binary distribution (faster install than

.tar.gz

)

twine

Securely upload packages to PyPI

pip

Install and manage Python packages

3. Recommended project structure

my_package/
│
├── my_package/          # main package directory
│   ├── __init__.py      # makes it a package
│   ├── module1.py       # module 1
│   └── module2.py       # module 2
│
├── tests/               # test code
│   └── test_module1.py
│
├── README.md            # project description
├── setup.py             # packaging configuration
└── requirements.txt    # optional dependencies

4. Writing setup.py (core configuration)

The setup.py file defines the package name, version, author, dependencies, and other metadata. Example:

from setuptools import setup, find_packages

setup(
    name="my_package",            # package name on PyPI
    version="0.1.0",               # semantic version
    author="Your Name",
    author_email="[email protected]",
    description="A short description of your package",
    long_description=open("README.md").read(),
    long_description_content_type="text/markdown",
    url="https://github.com/yourusername/my_package",
    packages=find_packages(),
    install_requires=[
        "requests>=2.25.0",
        "numpy>=1.20.0",
    ],
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
    ],
    python_requires=">=3.6",
)

5. Generating distribution packages ( .whl and .tar.gz )

Run the following commands in the project root:

# Install packaging tools
pip install setuptools wheel

# Build source and wheel distributions (output in
dist/
)
python setup.py sdist bdist_wheel

After execution, the dist/ directory contains:

my_package-0.1.0.tar.gz (source archive)

my_package-0.1.0-py3-none-any.whl (wheel archive)

6. Local test installation

Install the built wheel locally to verify it works:

pip install dist/my_package-0.1.0-py3-none-any.whl

Then import the package and check the version:

import my_package
print(my_package.__version__)  # should output 0.1.0

7. Publishing to PyPI

(1) Register a PyPI account and obtain an API token for twine .

(2) Install twine :

pip install twine

(3) Upload the distribution files:

twine upload dist/*

Provide your PyPI username/password or API token when prompted; after a successful upload, users can install the package with pip install my_package .

8. Advanced: version management and updates

Follow semantic versioning MAJOR.MINOR.PATCH : MAJOR : incompatible API changes MINOR : backward‑compatible feature additions PATCH : backward‑compatible bug fixes

To release a new version: Update the version field in setup.py . Re‑build the packages with python setup.py sdist bdist_wheel . Upload again using twine upload dist/* .

9. Frequently Asked Questions

Q1: How to make a command‑line tool installable via pip install ?

Add an entry_points section to setup.py :

entry_points={
    "console_scripts": [
        "my_command=my_package.cli:main",
    ],
}

Q2: How to include non‑Python files (e.g., data, config) in the package?

Use a MANIFEST.in file or the package_data argument:

setup(
    ...,
    package_data={"my_package": ["data/*.json"]},
    include_package_data=True,
)

Summary

Toolchain: setuptools + wheel + twine

Core steps: write setup.py → build dist/ → test locally → upload to PyPI

Best practices: proper versioning, dependency control, and thorough testing before release

PythonpackagingSetuptoolspypiwheeltwine
php中文网 Courses
Written by

php中文网 Courses

php中文网's platform for the latest courses and technical articles, helping PHP learners advance quickly.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.