Warming up the neural circuits...
By the end of this chapter you will:
Code you can't organize is code you can't reuse. As programs grow, putting everything in one file becomes unmaintainable. Modules and packages let you split code into logical units, reuse across projects, and share with others via PyPI.
# Full module import
import math
print(math.sqrt(16)) # 4.0
# Specific names
from math import sqrt, pi
print(sqrt(16)) # 4.0
# Alias
import numpy as np
from datetime import datetime as dt
# Wildcard (avoid!)
from math import * # imports everything — pollutes namespace| Style | Use when | Avoid when |
|---|---|---|
import module | Using many names from module | — |
from module import name | Using specific names | — |
import module as alias | Long module names | — |
from module import * | Never | Pollutes namespace |
# calculator.py
def add(a, b):
return a + b
if __name__ == "__main__":
# Only runs when executed directly
print(add(2, 3)) # 5myproject/
├── __init__.py
├── utils.py
├── models/
│ ├── __init__.py
│ ├── user.py
│ └── product.py
└── main.py# Import from package
from myproject.utils import helper
from myproject.models.user import User
# Import entire package
import myproject.modelsKey: __init__.py can be empty or run initialization code. Python 3.3+ has implicit namespace packages (no needed), but explicit is clearer.
# Check search path
import sys
print(sys.path)
# Common fixes:
# 1. Module not in sys.path
sys.path.insert(0, "/path/to/module")
# 2. Missing __init__.py
# Create empty __init__.py in the folder
Python searches for modules in this order:
| Mistake | Why it's wrong | Fix |
|---|---|---|
from math import * | Pollutes namespace | import math or specific names |
Naming file math.py | Shadows stdlib | Use different name |
| Circular imports | ImportError | Restructure code |
Missing __init__.py | Not recognized as package (pre-3.3) | Create empty file |
import module then module.func() | Works, but from module import func is cleaner for few imports | Use style consistently |
sqrt from math using three different styles.if __name__ == "__main__": do?math.py?from math import * bad? What should you use instead?Beginner:
"What's the difference between import module and from module import name?"
import moduleimports the entire module — you access names asmodule.name.from module import nameimports specific names directly into the current namespace. Useimport modulewhen using many names; usefrom module import namefor specific names.
"What does if __name__ == '__main__': do?"
It checks if the file is being executed directly (not imported). Code inside the guard runs only when the file is the main program. This makes modules both importable and runnable.
Senior:
"How does Python find modules when you import them?"
Python searches in order: (1) Current directory, (2) PYTHONPATH , (3) Standard library, (4) Site-packages (pip installs). The search path is stored in . You can modify it at runtime.
import module — full module. from module import name — specific names.__name__ == "__main__" runs only when executed directly.__init__.py. Subpackages = nested folders.I want to…
├── Import full module → import math
├── Import specific → from math import sqrt
├── Rename import → import numpy as np
├── Make importable + runnable → if __name__ == "__main__":
├── Create package → folder with __init__.py
└── Debug import → check sys.path, __init__.py, spellingWhat does if __name__ == '__main__': do?
# main.py
from calculator import add
print(add(2, 3)) # 5
# The __main__ guard does NOT runKey: __name__ is "__main__" when the file is executed directly. It's the module name when imported.
__init__.py| Error | Cause | Fix |
|---|---|---|
| ModuleNotFoundError | Not in sys.path | Add path or install package |
| ImportError | Can't find name in module | Check spelling, check init.py |
| AttributeError | Module doesn't have that name | Check module contents with dir() |
sys.path"What are circular imports and how do you fix them?"
Circular imports occur when module A imports module B, and module B imports module A. This causes ImportError. Fix: (1) Move shared code to a third module, (2) Use lazy imports (import inside function), (3) Restructure the dependency graph.