Phase 4 · Intermediate PythonModule 18~30 min read

Modules & Packages

Organize code across files with modules, packages, and imports.

What you'll learn

Real programs don't live in one giant file. Modules (individual .py files) and packages (folders of modules) let you split code into logical pieces and reuse it. You've already imported from the standard library — now you'll organize your own code the same way.

By the end you'll be able to:

  • Import in every style: import, from ... import, and as
  • Split code into your own modules
  • Group modules into a package
  • Use the if __name__ == "__main__" idiom

Importing modules

A module is just a .py file. import brings its names into your program. There are three common forms — import the whole module (and use dotted access), import specific names, or import under a shorter alias:

imports.py
import math                       # whole module
from random import randint       # one name from a module
import datetime as dt            # with an alias

print(math.sqrt(16))             # 4.0
print(randint(1, 6))             # e.g. 4
print(dt.date.today().year)      # e.g. 2026

Tip

Prefer import module or from module import specific_name over from module import *. The star import dumps every name into your namespace, hiding where things came from and risking silent name clashes. Explicit is better than implicit.

Your own modules

Importing your own code works identically — the file name (without .py) is the module name. Put reusable functions and constants in one file and import them from another:

project
# --- greetings.py ---
def hello(name):
    return f"Hello, {name}!"

PI = 3.14159

# --- main.py ---
import greetings
from greetings import PI

print(greetings.hello("Ada"))
print(PI)

When you import a module, Python runs it once and caches it, so top-level code executes a single time no matter how many files import it.

Packages

A package is a folder of modules. Historically it needed an __init__.py file (which can be empty, or expose the package's public API); modern Python also supports packages without it. You import with dotted paths that mirror the folders:

package layout
myapp/
├── __init__.py
├── models/
│   ├── __init__.py
│   └── user.py        # defines class User
└── utils/
    ├── __init__.py
    └── text.py        # defines slugify()

# elsewhere:
from myapp.models.user import User
from myapp.utils.text import slugify

Note

Python finds modules by searching the module search path (sys.path): roughly the current directory, then installed packages, then the standard library. If an import fails with ModuleNotFoundError, it's almost always because the module isn't on that path — often a working-directory or virtual-environment issue (next module).

The __name__ == "__main__" idiom

Every module has a built-in __name__ variable. When you run a file directly, __name__ is "__main__"; when it's imported, __name__ is the module's name. This lets a file provide reusable functions and a script entry point without the script code running on import:

calc.py
# calc.py
def add(a, b):
    return a + b

def main():
    print(add(2, 3))

if __name__ == "__main__":       # only runs when executed directly,
    main()                       # NOT when imported by another file

Key idea

Put script-only code (the part that does something) inside if __name__ == "__main__":. Then importing the module gives you its functions without side effects, and running it directly executes the script. It's the standard shape of almost every runnable Python file.

Recap & quick check

Key takeaways

  • A module is a .py file; import its names with import, from ... import, or an as alias.
  • Avoid from module import * — it pollutes your namespace and hides origins.
  • A package is a folder of modules, imported with dotted paths (myapp.utils.text).
  • Python runs a module once on first import and caches it; it finds modules via sys.path.
  • Guard script code with if __name__ == '__main__' so it runs only when executed directly.

Quick check

1. How do you import just randint from the random module?

2. Why avoid 'from module import *'?

3. What is a package?

4. When you run a file directly, __name__ equals…

5. Why guard code with if __name__ == '__main__'?

Your code is organized. But how do you manage the external packages a project needs? Next up: Module 19 — Virtual Environments, pip & the Ecosystem.