§ 2.5section 5 of 20·~5 min
Modules and packages
As code grows, you split it across files:
- A module is any
.pyfile. - A package is a folder of modules with an
__init__.pyfile.
lab/
library/ ← package
__init__.py ← runs on `import library`; decides what the package exposes
models.py ← Book, Member
library.py ← Library, BookNotAvailableError
storage.py ← save(), load()
tests/
test_library.py
# library/__init__.py
from library.library import BookNotAvailableError, Library
from library.models import Book, Member
__all__ = ["Book", "BookNotAvailableError", "Library", "Member"]
Now users write from library import Library, Book without knowing which file each lives in. This is how every real library presents a clean public surface.
Import styles:
import json # use it as json.dumps(...)
from pathlib import Path # use it as Path(...)
from library.models import Book # an absolute import from your own package: prefer this
Circular imports. If models.py imports library.py and library.py imports models.py, Python can fail with ImportError: cannot import name .... Keep the dependencies flowing one way: models → logic → storage/CLI.
Where Python looks. If you get ModuleNotFoundError: No module named 'library', you're probably running from the wrong folder. Run commands from the folder that contains the library/ package (here, lab/).