5.19. Writing modules

Any .py file is a module. Splitting a growing script across a few files keeps each file short and lets common helpers be shared between scripts.

5.19.1. Splitting a script

Pull a related group of functions out into their own file:

camera_utils.py:

def banner():
    print("OpenMV")

def label(text):
    return "[" + text + "]"

main.py:

import camera_utils

camera_utils.banner()
print(camera_utils.label("ready"))

Output:

OpenMV
[ready]

The two files sit side by side in the same directory. When main.py runs, import camera_utils reads camera_utils.py once, executes its top-level statements, and binds the resulting module object to the name camera_utils in main. A second import camera_utils from anywhere else returns the same object – modules are cached after their first load.

A module’s name comes from its filename, so camera_utils.py gets imported as import camera_utils.

5.19.2. Multi-file modules (packages)

A module can also be a directory of files rather than a single .py. The directory’s name becomes the module name, and the files inside are its submodules:

camera_utils/
    __init__.py
    text.py
    timing.py

__init__.py is the file that runs when the package itself is imported; it can be empty, or it can re-export selected names from the submodules. The submodules are reached with a dotted name:

import camera_utils.text
from camera_utils.timing import elapsed

camera_utils.text.label("ready")

Inside the package, submodules can reach each other either by the full dotted name or by a relative import that uses a leading dot to mean “this package”:

camera_utils/timing.py:

from . import text             # the sibling submodule

def stamp(value):
    return text.label(str(value))

To pull in a specific name instead, name it after the dotted sibling:

from .text import label

def stamp(value):
    return label(str(value))

Relative imports keep a package self-contained: renaming the package directory does not require editing every submodule.

Use a package when a single file grows past a comfortable size, or when a set of related modules belongs together under one namespace. For everyday scripts a single .py file is enough.

5.19.3. The __name__ guard

Every module has a built-in name __name__. Its value depends on how the file is being used:

  • When the file is run directly, __name__ is set to the string "__main__".

  • When the file is imported by another script, __name__ is set to the module name – the filename without .py.

The idiom that uses this is:

label_util.py:

def label(text):
    return "[" + text + "]"

if __name__ == "__main__":
    print(label("self-test"))

Output (when run directly):

[self-test]

When the same file is imported instead, __name__ is set to the module name, so the if block is skipped and nothing extra runs:

>>> import label_util
>>> label_util.__name__
'label_util'

Use the pattern to attach a quick smoke test or demo to a library file without disturbing scripts that import it.