Modules & Imports (import, from, as, custom modules, name) - Python Tutorial #17
Video: Modules & Imports (import, from, as, custom modules, name) - Python Tutorial #17 by Taught by Celeste AI - AI Coding Coach
Python Modules and Imports: import, from, as, name
import math— load a module.from math import sqrt— bring one name into your namespace.import datetime as dt— alias.if __name__ == "__main__":— run only when executed directly. Modules are how Python projects scale beyond a single file.
A module is a Python file. A package is a directory of modules. Imports are how one file uses code from another.
Importing a module
import math
print(math.sqrt(144)) # 12.0
print(math.pi) # 3.141592653589793
print(math.ceil(3.2)) # 4
print(math.floor(3.8)) # 3
import math makes the math module available as math. Access its contents with dotted notation: math.sqrt, math.pi.
The first time import math runs, Python:
1. Finds math (built-in, then site-packages, then current directory).
2. Executes the module's top-level code.
3. Binds the module object to the name math.
Subsequent imports just retrieve the cached module — no re-execution.
from ... import
from random import randint, choice
print(randint(1, 10)) # no need to write random.randint
print(choice(["apple", "banana"]))
from module import name brings name directly into your namespace. Use when you only need a few specific functions.
Comma-separate multiple imports:
from math import sqrt, pi, ceil, floor
You can do from module import * — but don't. It pollutes your namespace and hides where names came from.
import as
import datetime as dt
now = dt.datetime.now()
print(now.strftime("%Y-%m-%d"))
import X as Y aliases the module. Useful when:
- The module name is long:
import numpy as np,import pandas as pd. - The name conflicts with a local variable.
- A widely-known convention:
np,pd,pltfor matplotlib.
You can alias inside from ... import too:
from helpers import calculate_area as area
Standard library tour
import math # numerical functions
import random # randomness
import datetime # dates and times
import os # OS interactions, paths
import sys # interpreter, argv
import json # JSON parsing
import re # regex
import csv # CSV files
import collections # Counter, defaultdict, deque
import itertools # combinatorial iterators
import functools # caching, reduce, partial
import pathlib # modern path handling
These ship with Python — no install needed. The standard library is huge; lessons later in this series cover each in depth.
Writing your own module
Any .py file is a module. Save this as helpers.py:
# helpers.py
def greet(name):
return f"Hello, {name}!"
def calculate_area(length, width):
return length * width
PI = 3.14159
Then in another file in the same directory:
# main.py
import helpers
print(helpers.greet("Alice"))
print(helpers.calculate_area(10, 5))
Or:
from helpers import greet, calculate_area
print(greet("Alice"))
print(calculate_area(10, 5))
The module name is the filename without .py.
name == "main"
# helpers.py
def greet(name):
return f"Hello, {name}!"
if __name__ == "__main__":
print("Testing helpers module:")
print(greet("World"))
When Python runs a file directly, __name__ is "__main__". When the file is imported, __name__ is the module name ("helpers").
The if __name__ == "__main__": guard runs the test/demo code only when the file is run directly, not when imported. Standard pattern for "library + script" files.
Three import styles compared
# Style 1: import module
import helpers
helpers.greet("Alice")
helpers.calculate_area(10, 5)
# Style 2: from module import
from helpers import greet, calculate_area
greet("Alice")
calculate_area(10, 5)
# Style 3: import as
from helpers import calculate_area as area
area(10, 5)
When to use which:
- Style 1 — many functions used; preserves module prefix for clarity.
- Style 2 — a few specific functions used heavily; less typing.
- Style 3 — long names or conflicts.
Packages: directories of modules
A package is a directory with an __init__.py file (which can be empty):
myproject/
__init__.py
utils.py
database.py
models/
__init__.py
user.py
post.py
import myproject.utils
from myproject.database import connect
from myproject.models.user import User
Dotted paths mirror directory structure. The __init__.py runs when the package is first imported — useful for re-exporting, version, etc.
For modern projects (Python 3.3+), namespace packages can omit __init__.py, but most projects still include them for clarity.
sys.path: where Python searches
import sys
print(sys.path)
# ['', '/path/to/your/script', ..., 'site-packages']
Python looks for modules in:
- The directory of the running script.
PYTHONPATHenvironment variable directories.- Standard library locations.
site-packages(where pip installs).
For projects, install your code as a package (pip install -e .) rather than fiddling with sys.path.
Relative vs absolute imports
# absolute (preferred):
from myproject.models.user import User
# relative (inside the same package):
from .models.user import User # one level up
from ..utils import helper # two levels up
Use absolute imports unless the relative form is shorter and clearly within the same package. Relative imports break if you move files; absolute imports remain stable.
Reload during development
If you're in a REPL and you've changed a module:
from importlib import reload
import helpers
reload(helpers)
In Jupyter, use the %autoreload magic. For scripts, just re-run.
dir() and help()
import math
print(dir(math)) # all names in the module
print(help(math.sqrt)) # docstring
dir(module) lists everything exported. Useful for exploring a new library.
Common stumbles
Circular imports. A imports B, B imports A. Python loads each file once, so the second import gets a partial module. Refactor: extract the shared code into a third module.
Same-name shadow. Naming your file random.py shadows the standard library random. Don't name files after stdlib modules.
Star imports. from module import * — pollutes namespace, hides where names come from, breaks linters. Avoid.
Forgetting if __name__ == "__main__":. Without it, import causes the demo code to run.
Modifying sys.path. Tempting, brittle. Install your package properly instead.
Cached old version. Edited a module, rerunning script shows old behavior. Restart your REPL or call importlib.reload.
What's next
Lesson 18: JSON. Reading and writing JSON files; json.loads, json.dumps, encoding nested structures.
Recap
import module for full module; from module import name for specific names; import as for aliases. Any .py file is a module; any directory with __init__.py is a package. if __name__ == "__main__": to make a file work as both library and script. Avoid from X import *. Use absolute imports for stability. Watch out for circular imports and stdlib-shadowing filenames.
Next lesson: JSON.