← Back to Chapters

Python Packaging

? Python Packaging

⚡ Quick Overview

Python packaging is about turning your code into a reusable, installable package that can be shared across projects or published on PyPI. A package typically includes:

  • A directory with Python modules and an optional __init__.py file.
  • Metadata files describing the project (name, version, dependencies).
  • Build configuration (e.g., pyproject.toml).

Once packaged, your project can be installed with tools like pip and imported just like any other library.

? Key Concepts

  • Module – a single .py file.
  • Package – a directory containing modules (often with __init__.py).
  • Project root – top-level folder of your library/application.
  • pyproject.toml – modern config file describing how to build/install a project.
  • Source distribution (sdist) – archive of the source code.
  • Wheel – built binary distribution (fast to install).

? Project Structure and Files

A minimal library project might look like this:

? Example Project Structure
# Project directory structure
myproject/
    pyproject.toml
    README.md
    src/
        mypackage/
            __init__.py
            core.py

The src/mypackage directory is the actual package. Code inside core.py can be imported with:

? Importing from the Package
# Import function from the package
from mypackage.core import some_function

? Code Examples

? Creating a Simple Package

Example of a simple package with one function.

? Package Code (src/mypackage/core.py)
# Define a greeting function
def greet(name: str) -> str:
    return f"Hello, {name}!"
? Package Init (src/mypackage/__init__.py)
# Expose greet at the package level
from .core import greet

# Control what gets imported with *
__all__ = ["greet"]

? Basic pyproject.toml

pyproject.toml tells build tools how to build/install your package and includes metadata like name, version, and dependencies.

? View pyproject.toml Example
# Build system configuration
[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"

# Project metadata
[project]
name = "mypackage"
version = "0.1.0"
description = "A simple example package"
authors = [{ name = "Your Name", email = "you@example.com" }]
readme = "README.md"
requires-python = ">=3.8"
dependencies = []

?️ Building and Installing the Package

Once your project is configured, you can build and install it locally.

? Build & Install Commands
# From the project root (where pyproject.toml is located)

# Build source and wheel distributions (requires build package)
python -m pip install --upgrade build
python -m build

# Install the built package locally
python -m pip install dist/mypackage-0.1.0-py3-none-any.whl

? Live Output and Explanation

? What Happens When You Install

  • Running python -m build creates files like mypackage-0.1.0.tar.gz and a .whl file in the dist/ folder.
  • pip install dist/mypackage-0.1.0-py3-none-any.whl copies the package into your Python environment.
  • After installation, you can open a Python shell and run: from mypackage import greet and then greet("World") to get "Hello, World!".

This is the same behavior as any package you install from PyPI, but now it’s your own code being reused.

? Use Cases

  • Sharing reusable utilities across multiple internal projects.
  • Publishing open-source libraries on PyPI.
  • Structuring large applications into well-organized components.
  • Distributing command-line tools written in Python.

? Tips & Best Practices

  • Use a clear directory structure (e.g., src/mypackage layout).
  • Keep metadata (name, version, dependencies) in pyproject.toml rather than custom scripts.
  • Pin minimum Python version with requires-python to avoid compatibility issues.
  • Include a README.md so users understand how to install and use your package.
  • Use __all__ in __init__.py to control what is exported from the package.

? Practice Tasks

  • Create a new project with src/mypackage and add at least two functions in core.py.
  • Write a pyproject.toml with your own name, description, and version.
  • Build the package using python -m build and install it locally with pip.
  • Open a Python shell and import your package, calling your functions to verify it works.
  • Extend your package with a second module (e.g., utils.py) and re-build/re-install.