Modules and packages

Split code across files, understand what import actually does, and know why the second import is free.

12of 24
≈ 12Min read
5Parts

A module is a file

import greet binds one name, greet, to a module object; the functions live on it. from greet import hello binds the function directly — shorter at the call site, and it loses the context that says where hello came from. For anything but a very familiar name, the qualified form reads better.

py
# greet.py
GREETING = "hi"

def hello(name):
    return f"{GREETING}, {name}"
four ways to bring it in
import greet                      # greet.hello("ada")
import greet as g                 # g.hello("ada")
from greet import hello           # hello("ada")
from greet import hello as hi     # hi("ada")

from greet import *               # don't. It hides where names came from.

What import does, once

This is why editing a file has no effect on a program already running, and why a module’s top level should only define things. Anything expensive or side-effecting at module level happens exactly once, at an unpredictable moment, in an order decided by whoever imported first.

py
import sys
"greet" in sys.modules      # True after the first import

import importlib
importlib.reload(greet)     # run the file again — for a REPL, not for production
del sys.modules["greet"]    # the blunt version

Where it looks

Name a file after a standard-library module — random.py, json.py, email.py — and your file wins, because the script directory comes first. The resulting error is always confusing and never mentions the real cause.

py
import sys
sys.path      # a list, searched in order:
              #   the directory of the script being run (or the cwd)
              #   anything in PYTHONPATH
              #   the standard library
              #   site-packages

__name__, and the guard

__name__ is "__main__" when the file is the one being run, and the module’s own name when it is imported. The guard means "only do this if I am the program, not a library" — without it, importing your script runs it.

py
def main():
    ...

if __name__ == "__main__":
    main()

Packages

A package is a directory Python treats as a module. Since 3.3 __init__.py is not strictly required, but including it keeps the boundary explicit and lets the package choose what it exports.

text
shop/
  __init__.py      # marks the package; often empty, sometimes the public surface
  cart.py
  pricing/
    __init__.py
    tax.py
py
from shop.pricing import tax          # absolute — always prefer this
from .pricing import tax              # relative, only inside the package itself
from shop import cart                 # __init__.py decides what shop exposes

Practice