A detailed guide to Python packages, covering creation, management, and distribution with practical examples.
Last modified March 25, 2025
This guide provides an in-depth exploration of Python packages, merging best practices from leading tutorials to enhance your skills in organizing, managing, and distributing Python code effectively.
A Python package is a structured collection of modules grouped under a common namespace, typically within a directory containing an init.py file, though this is optional since Python 3.3. This organization aids in modular programming and code reuse.
In large projects with numerous modules, packages are essential. For instance, database-related modules can reside in a database package, while UI code can be organized in a ui package.
Built-in packages are located in directories such as /usr/lib/python3.5 on Debian Linux or C:\Users\Jano\AppData\Local\Programs\Python\Python36-32\Lib\site-packages on Windows. Third-party packages install to /usr/local/lib/python3.5/dist-packages or C:\Users\Jano\AppData\Local\Programs\Python\Python36-32\libs.
This example demonstrates creating a simple package for mathematical operations using an empty init.py.
math_ops/init.py
“““Initialization file for the math_ops package.”””
Explanation: The init.py file marks the directory as a package. Here, it is empty but includes a docstring for clarity, serving as a placeholder for potential initialization code.
math_ops/calculations.py
def cube(number): “““Returns the cube of a given number.””” return number ** 3
def square(number): “““Returns the square of a given number.””” return number ** 2
Explanation: The calculations.py module defines two functions: cube and square. Each includes a docstring for documentation, enhancing code readability and maintainability.
main.py
#!/usr/bin/python from math_ops.calculations import cube, square
print(f"Cube of 4: {cube(4)}") # Output: Cube of 4: 64 print(f"Square of 5: {square(5)}") # Output: Square of 5: 25
Explanation: This script imports specific functions from the math_ops.calculations module using dot notation. It demonstrates how to access package contents and displays formatted output for clarity.
The pip tool is crucial for managing third-party Python packages efficiently.
Terminal
pip install arrow
pip install numpy pandas –user
pip uninstall arrow -y
Explanation: These commands illustrate installing the arrow library, adding multiple packages with the –user flag for user-specific installation, and removing a package with the -y flag to skip confirmation. This showcases practical package management.
Enhance usability by defining imports in init.py.
math_ops/init.py
“““Initialization file for the math_ops package.””” from .calculations import cube, square version = “1.0.0”
Explanation: This init.py imports functions from calculations.py into the package namespace and defines a version attribute. The relative import (with .) ensures proper module referencing within the package.
main.py
#!/usr/bin/python from math_ops import cube, square
print(f"Cube of 3: {cube(3)}") # Output: Cube of 3: 27 print(f"Square of 6: {square(6)}") # Output: Square of 6: 36
Explanation: By importing directly from math_ops, this script simplifies access to functions without specifying the module name, demonstrating the convenience of init.py imports.
Subpackages provide further organization within a package hierarchy.
constants/init.py
“““Initialization for constants package.””” from .data import names
Explanation: This init.py file initializes the constants package and imports the names tuple from the data module, making it directly accessible.
constants/data.py
“““Module containing constant data.””” names = (‘Jack’, ‘Jessica’, ‘Robert’, ‘Lucy’, ‘Tom’) colours = (‘yellow’, ‘blue’, ‘red’, ‘orange’, ‘brown’)
Explanation: The data.py module defines two tuples, names and colours, with a docstring for context. These constants can be imported individually or via the package.
constants/numbers/init.py
“““Initialization for numbers subpackage.””” from .myintegers import integers
Explanation: This init.py file marks numbers as a subpackage and imports the integers tuple from myintegers.py, simplifying access within the subpackage.
constants/numbers/myintegers.py
“““Module defining integer constants.””” integers = (2, 3, 45, 6, 7, 8, 9)
Explanation: This module defines a tuple of integers with a docstring, providing a clear purpose. It is accessible through the numbers subpackage.
main.py
#!/usr/bin/python from constants import names from constants.numbers import integers
print(f"Names: {names}") print(f"Integers: {integers}")
Explanation: This script imports names from the constants package and integers from the numbers subpackage, using dot notation to navigate the hierarchy. It prints both tuples with descriptive labels.
Since Python 3.3, namespace packages can omit init.py.
utils/text/manipulate.py
“““Module for text manipulation.””” def reverse_string(text): “““Reverses the given text.””” return text[::-1]
Explanation: This module defines a reverse_string function within a namespace package structure. No init.py is needed, leveraging Python’s implicit namespace support.
main.py
#!/usr/bin/python from utils.text.manipulate import reverse_string
print(reverse_string(“Python”)) # Output: nohtyP
Explanation: The script imports and uses the reverse_string function from the namespace package, demonstrating a lightweight approach to package organization without initialization files.
Modern distribution uses pyproject.toml for configuration.
pyproject.toml
[build-system] requires = [“setuptools>=42”, “wheel”] build-backend = “setuptools.build_meta”
[project] name = “math_ops” version = “1.0.0” authors = [{name=“Jan Bodnar”, email=“admin@zetcode.com”}] description = “A package for mathematical operations” readme = “README.md” requires-python = “>=3.8” dependencies = [“numpy>=1.21.0”]
Explanation: This file defines the build system and project metadata, including dependencies like numpy. It adheres to PyPA standards, ensuring compatibility and ease of distribution.
Terminal
python -m build
python -m twine upload dist/*
Explanation: These commands build the package into distribution files and upload them to PyPI, making it available for others to install via pip. This is a professional distribution workflow.
The arrow package is a third-party library for date and time manipulation.
Terminal
ls /usr/local/lib/python3.5/dist-packages/arrow
Explanation: This command shows the structure of the arrow package installed via pip on Debian Linux, highlighting its modular design as a collection of Python files.
This example integrates data processing capabilities.
data_analyzer/init.py
“““Initialization for data_analyzer package.””” from .stats import calculate_average
Explanation: The init.py file initializes the package and imports calculate_average for direct access, enhancing usability.
data_analyzer/stats.py
def calculate_average(numbers): “““Calculates the average of a list of numbers.””” return sum(numbers) / len(numbers) if numbers else 0
def calculate_median(numbers): “““Calculates the median of a list of numbers.””” sorted_nums = sorted(numbers) n = len(sorted_nums) return sorted_nums[n//2] if n % 2 else (sorted_nums[n//2 - 1] + sorted_nums[n//2]) / 2
Explanation: This module provides statistical functions with robust error handling (e.g., empty list check) and clear docstrings, making it practical for data analysis tasks.
main.py
#!/usr/bin/python from data_analyzer import calculate_average from data_analyzer.stats import calculate_median
data = [1, 2, 3, 4, 5] print(f"Average: {calculate_average(data)}") # Output: Average: 3.0 print(f"Median: {calculate_median(data)}") # Output: Median: 3
Explanation: The script uses the data_analyzer package to compute and display statistical measures, showcasing a real-world application of package functionality.
My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.
List all Python tutorials.