25. Modules and import
Every script you have written so far has lived in one file. Real
programs grow past that. Python splits programs across files using
modules: a module is a .py file that
exposes functions (and variables) for other files to use.
A module is just a Python file
No special wrapper is needed. Create a file, put functions in it, and it is a module:
# file: greet.py
def hello(name):
print(f"Hello, {name}!")
def bye(name):
print(f"Goodbye, {name}.")Two things to notice:
- The file does no work when imported. Nothing prints, nothing runs. It only defines functions.
- There is no return statement, no wrapper table, no ceremony. A
.pyfile is a module by virtue of existing.
Using a module with
import
Another file loads it with import:
# file: main.py
import greet
greet.hello("Keiko")
greet.bye("Keiko")import greet does three things:
- Finds a file called
greet.pyon the Python path. - Runs it (only the first time — see the note below).
- Binds the name
greetin the current file so you can access its contents viagreet.hello,greet.bye, etc.
Python caches imported modules. If two files both
import greet, Python loads greet.py once and
both files share the same module object. This is good — it means modules
are cheap to import from anywhere.
from module import name
If you only need one or two names from a module, import them directly:
from greet import hello
hello("Keiko") # no "greet." prefix neededTo import several names at once:
from greet import hello, byeThis puts hello and bye directly into the
current namespace. There is no greet. prefix required, but
there is also no greet. to tell a reader where these
functions came from. For small, clearly named functions it is fine; for
large modules, import greet and using
greet.hello is clearer.
import module as alias
Long module names can be given a shorter alias:
import math_helpers as mh
print(mh.double(7))
print(mh.triple(7))This is common in the Python ecosystem — you will see
import numpy as np and import pandas as pd
everywhere. For your own small modules, aliases are optional.
Where Python looks
Python looks in the current working directory first, then a list of
standard library and installed-package paths. The simplest layout is to
put main.py and greet.py in the
same folder, then run from that folder:
cd exercises/25/examples
python main.py
If you stay at the repo root and run
python exercises/25/examples/main.py, Python may not find
greet.py because the search starts from the script's
directory. Run from the same folder to keep it simple.
Private helpers inside a module
Functions that you do not want other files to call can be left as
plain functions — just do not mention them in the module's documentation
or expose them via from module import *. The convention is
to prefix their names with an underscore:
# file: math_helpers.py
def _clamp(x, lo, hi):
if x < lo:
return lo
if x > hi:
return hi
return x
def double(x):
return _clamp(x * 2, -100, 100)_clamp starts with _, signalling "internal
use only". Other files can call
math_helpers._clamp if they try, but the underscore is a
strong convention that says not to.
Homework
The Part 5 homework uses two files per problem: a
module file and a main.py that uses it. Each problem lives
in its own sub-folder so the two files sit together. Open a terminal,
cd into that folder, then run
python main.py.
Problem 1 — Greet module
Folder: exercises/25/homework/01-greet-module/.
Finish greet.py so it exposes hello(name)
and bye(name). The main.py file is provided
and already calls both functions.
Problem 2 — Math helpers
Folder: exercises/25/homework/02-math-helpers/.
Build a math_helpers.py module with at least two
functions:
double(x)returnsx * 2.triple(x)returnsx * 3.
main.py calls both and prints the results.
Problem 3 — Counter
Folder: exercises/25/homework/03-counter/.
Build a counter.py module that exposes three
functions:
increment()— increases the counter by 1.get()— returns the current value.reset()— sets the counter back to 0.
The counter itself is a module-level variable inside
counter.py. It must persist across calls (think back to the
scope discussion at the end of Chapter 21).
Challenge — String utilities
Folder: exercises/25/homework/04-string-utils/.
Build a string_utils.py module with at least three
functions of your own. Suggestions:
shout(s)returnssin upper case with!appended.echo(s, n)returnssrepeatedntimes with spaces between.reverse_words(s)returns the words ofsin reverse order.
The last one is a stretch — you will need to split the string into words and reverse the list. If that is too much, swap it for anything else of your own.
Stuck or finished? Open the homework solutions page.