Python Packages

A Python package is a directory-based namespace that groups related modules under one importable name. This lesson focuses on the low-level idea of a package, the syntax used to import it, and the directory structure that makes it work.

What Is a Package?

A module is usually one .py file. A package is a directory that contains one or more modules and exposes them through a shared namespace. Packages help you organize code, avoid name collisions, and publish reusable libraries.

At a low level, a package gives you three things:

  • a directory structure for related code,
  • a namespace such as shop or shop.billing,
  • a reusable import surface for other modules and applications.

Package Syntax

Most package syntax in Python is import syntax. You can import the whole package, a module inside the package, or a specific symbol from one module.

import shop
import shop.billing
from shop import billing
from shop.billing import create_invoice

These forms have different effects:

  • import shop.billing keeps the full qualified path.
  • from shop import billing adds billing directly to local scope.
  • from shop.billing import create_invoice imports one public symbol directly.

Package Layout

A minimal package is a directory with Python modules and usually an __init__.py file. That file can be empty, or it can expose public imports and package metadata.

shop/
  __init__.py
  billing.py
  inventory.py

Example contents:

# shop/billing.py
def create_invoice() -> str:
    return "invoice created"

# shop/__init__.py
from .billing import create_invoice

Now another module can do this:

from shop import create_invoice

print(create_invoice())

Use a Package

To use a built-in or third-party package, import it into your program and access members through the package or module namespace.

Example:

import math

print(math.sqrt(2))

Output:

1.4142135623730951

For more information on built-in modules, refer to the Python Standard Library documentation: Python Standard Library.

Absolute and Relative Imports

Inside a package, modules can import siblings by using absolute or relative imports.

# absolute import
from shop.billing import create_invoice

# relative import inside shop/inventory.py
from .billing import create_invoice

Absolute imports are easier to read at project scale. Relative imports are useful when modules are tightly coupled inside the same package.

Core Packages

Python ships with a large standard library. These modules are available without installing third-party packages.

Package Description
abcAbstract base classes
collectionsData structures and helpers
datetimeDates and times
mathMathematical functions
osOperating system interface
pathlibFilesystem paths
subprocessSubprocess management
typingType hints and contracts

Third Party Packages

Third-party packages are published outside the standard library and installed through package indexes such as PyPI. They extend Python with framework, networking, data, and scientific tooling.

Package Name Purpose Description
requestsHTTP clientSimple HTTP requests and response handling.
FlaskWeb frameworkLightweight backend framework for APIs and web apps.
DjangoWeb frameworkFull-stack framework with batteries included.
NumPyNumerical computingArrays, vectorized math, and scientific operations.
pandasData analysisTabular data processing and transformation.

Package Managers

A Python package manager installs, updates, and resolves package dependencies. It is the operational layer that turns package metadata into a working local environment.

  • pip: default installer for Python packages from package indexes.
  • Poetry: dependency manager and packaging workflow with lock files.
  • Conda: environment and binary dependency manager used heavily in scientific computing.

Package managers are essential because your project often depends on many libraries that must work together under compatible versions.

Benefits of Using a Python Package Manager

  • Installation: install packages with deterministic commands.
  • Dependency resolution: avoid version conflicts between libraries.
  • Reproducibility: rebuild the same environment on another machine.
  • Security: update vulnerable dependencies more systematically.

Recommendations

If you are new to Python, start with pip and virtual environments. If you need stronger project packaging workflows, learn Poetry. If you work in data-heavy environments with compiled binary dependencies, study Conda.

Create a Package

To create a package in Python, create a directory, add __init__.py, then place related modules inside it. For modern packaging, define metadata in pyproject.toml.

Steps:

  1. Create a new directory for your package.
  2. Create a file named __init__.py in the package directory.
  3. Add one or more modules to the package.
  4. Create a pyproject.toml file for metadata.
  5. Install the package in editable mode during development.
mypackage/
  pyproject.toml
  src/
    mypackage/
      __init__.py
      hello.py
# src/mypackage/hello.py
def hello_world() -> None:
    print("Hello, world!")

# src/mypackage/__init__.py
from .hello import hello_world
[build-system]
requires = ["setuptools>=68", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "mypackage"
version = "0.1.0"
description = "Example Python package"
readme = "README.md"
requires-python = ">=3.11"
python -m pip install -e .

Once installed, you can import the package into your Python programs:

import mypackage

mypackage.hello_world()

Public API Design

A package should expose a small public API and hide internal details when possible. The public API is usually what you re-export in __init__.py and document for users.

  • Put stable import paths in the package root.
  • Keep experimental helpers deeper in internal modules.
  • Avoid forcing callers to import many nested implementation filenames.

Package Lab

  1. Create a package with two modules and one shared package namespace.
  2. Use both absolute and relative imports.
  3. Export one public function from __init__.py.
  4. Install the package with pip install -e . and import it from a separate test script.
# test_app.py
import mypackage

mypackage.hello_world()

This structure is the low-level foundation behind larger frameworks, internal company libraries, and publishable PyPI projects.


Challenge: Build a small package, install it in editable mode, and import it from a separate script.