Python Part I · Module 13 · Modules, Packages and Imports
What a Module Is, and Why import Exists
Twelve modules of this course have used nothing but names Python gives you for free — print, len, sorted, str, the collection types and the statements that drive them. It would be reasonable to conclude that is the language. It is a small fraction of it. Almost everything an automation script actually needs — mathematics, dates, JSON, file paths, running other programs — lives outside the core in separate files that ship with Python and are not loaded until you ask. This chapter is about the statement that asks, and about what you get back when you do, which turns out to be an ordinary object obeying rules you already know.
Foundation15 min readPythonPart IFundamentalsModulesimport
Part I · Module 13 · Chapter 13.1 · What a Module Is, and Why import Exists
1. The Wall You Have Not Hit Yet
Here is a question every script eventually asks: what is the square root of 16?
Everything in Modules 1 to 12 is available, and none of it answers that. There is no sqrt built in, and writing one properly is a numerical-methods problem rather than a Python problem.
print(sqrt(16))NameError: name 'sqrt' is not definedChapter 1.11's NameError, from a name that genuinely does not exist — not a typo, not a scope problem. Python has square roots; they are simply not switched on.
2. import Switches Them On
import math
print(math.sqrt(16))
print(math.floor(3.7))
print(math.pi)4.0
3
3.141592653589793Two new things. import math makes a collection of mathematical tools available, and math.sqrt(...) reaches into it for one of them.
A module is a file of Python that someone else wrote. math is one of several hundred that ship with Python itself, and import is how a script says I would like to use that one.
3. Why It Is Not All Just There
A fair question: if sqrt ships with Python, why is it not simply available like len?
Because "everything that ships with Python" is enormous — mathematics, dates, compression, networking, databases, audio, HTML parsing — and almost every script wants a handful of it. Loading all of it for every script would be slow and would fill the name space with thousands of names you did not ask for, any of which could collide with yours.
So the design is the opposite: the core stays small, and you name what you need. A consequence worth noticing immediately is that the import lines at the top of a file are a summary of what it depends on, written by the author whether they meant to document it or not.
4. A Module Is an Object
This is the fact that makes everything else follow without new rules:
import math
print(type(math))
print(math.__name__)<class 'module'>
mathimport math binds the name math to a value whose type is module. That is the same thing def does for a function (Chapter 11.2, Section 3) and the same thing = does for anything else — Chapter 2.3's rule, unchanged.
And math.sqrt is attribute access: reach into that object for something it holds. You have done this since Module 4 without naming it — line.upper(), results.append(...), status.items() are all the same dot.
What a module holds is inspectable. dir() lists the names in it:
import math
names = dir(math)
print(type(names))
print("sqrt" in names)
print("floor" in names)
print("definitely_not_a_real_function" in names)
print(len(names) > 20)<class 'list'>
True
True
False
TrueAn ordinary list of strings, which you can search with everything from Module 5. (Its exact length changes between Python versions, so the check above asks whether it is large rather than quoting a number.)
5. The Dot Is Doing Real Work
math.sqrt and a bare sqrt are not the same thing, and the difference is useful:
import math
print(sqrt(16))NameError: name 'sqrt' is not definedImporting the module does not put sqrt into your file's names. It puts math there, and sqrt lives inside it.
That is deliberate. Two modules can both contain a load or a parse or an open without any ambiguity, because the dotted name says which one you mean. Chapter 13.2 covers the other form, which does bring names directly in — along with the collision it makes possible.
6. A Module Is Loaded Once
A module's top-level code runs when it is first imported, and not again on later imports. Python remembers what it has already loaded.
Here is that in two files — the first time this course has used more than one:
MESSAGE = "loaded"
print("greeting.py top level ran")import greeting
import greeting
print("imported twice, message is:", greeting.MESSAGE)greeting.py top level ran
imported twice, message is: loadedgreeting.py top level ran appears once, though import greeting is written twice. The second import found the module already loaded and simply bound the name again.
That matters in both directions. It means importing is cheap to repeat, and it means anything at a module's top level happens as a side effect of importing it — which is the problem Chapter 13.6 exists to solve.
7. When the Module Is Not There
import nosuchmoduleModuleNotFoundError: No module named 'nosuchmodule'Precise and well named. In practice it means one of three things: a typo in the module name, a module that ships separately and has not been installed, or your own file not being where Python looked — which Chapter 13.5 covers.
A related error appears when the module exists but the name inside it does not. from math import nosuchname raises ImportError: cannot import name 'nosuchname' from 'math', followed by the full path of the file it searched. That path is specific to your machine and Python version, which is why this chapter does not quote the message in full — Chapter 13.2 covers the from form properly.
8. Where the Import Lines Go
By convention, every import sits at the top of the file, before any other code:
import math
import json
ANGLES = [0, 30, 45]
print(json.dumps({"count": len(ANGLES)}))
print(round(math.cos(0), 3)){"count": 3}
1.0Python does not require this — import is a statement and runs wherever it appears. The convention exists because the import block is the file's dependency list, and a reader wants it in one place rather than scattered through four hundred lines.
That reason is the same one Chapter 11.2 Section 6 gave for putting defs at the top: what this file needs and what this file does are different questions, and separating them makes both answerable at a glance.
9. Predict, Run, Observe
import math
# A
print("A:", math.sqrt(81))
# B
print("B:", type(math).__name__, math.__name__)
# C
print("C:", "pi" in dir(math), "tau" in dir(math))
# D
alias_test = math
print("D:", alias_test.sqrt(9))The verified output:
A: 9.0
B: module math
C: True True
D: 3.0A — sqrt always returns a float, even for a perfect square.
B — the type is module; the module knows its own name.
C — dir() is searchable with in, like any list.
D — binding the module to a second name works, because it is an ordinary value. Chapter 13.3 covers the proper way to do this.
10. Exercises
Exercise 1 — the wall. Try to use sqrt, floor and pi without importing anything. Record the errors, then make all three work with one line.
Exercise 2 — it is an object. Print the type of math, its __name__, and whether "log" is in dir(math). Say in one sentence what kind of thing import bound.
Exercise 3 — the dot. Explain in two sentences why import math does not make sqrt available on its own, and give one practical benefit of that.
Exercise 4 — loaded once. Write a two-file example where the imported file prints at its top level and the importing file imports it three times. Predict how many times the message appears, then verify.
Exercise 5 — the missing module. Import a module that does not exist and record the exact error. Give three different real-world causes for it.
Exercise 6 — explore one. Import statistics and use dir() to find out whether it has mean, median and mode. Then call the ones it has on [1, 2, 2, 3].
Exercise 7 — import placement. Move an import to the middle of a working script and confirm it still runs. Say why the convention puts it at the top anyway.
Exercise 8 — read the dependencies. For a file beginning with import math, import json and import csv, say in one sentence each what you can infer about what the file does.
11. Summary
- Most of Python's usefulness is outside the language core, in separate files that are not loaded until you ask.
- A module is a file of Python someone else wrote, and several hundred ship with Python itself.
import mathbinds the namemathto a value whose type ismodule— an ordinary assignment.math.sqrtis attribute access, the same dot you have used since Module 4. No new syntax is involved.dir(module)returns an ordinary list of the names it holds, searchable within.- Importing does not bring the inner names into your file — that is what makes two modules able to hold the same name safely.
- A module's top-level code runs once, on first import; later imports reuse it.
- So anything at a module's top level happens as a side effect of importing it — the problem Chapter 13.6 solves.
ModuleNotFoundErrormeans a typo, a module not installed, or your file not where Python looked.- Imports go at the top, because that block is the file's dependency list.
The next chapter covers the second form of the statement, and the collision it can cause.
Where this fits
Part of the Python curriculum.
