A module is a single file; a package is a directory that groups modules
A module is any file that Python can import as a unit, usually a .py file but also .pyc, .so, or .pyd extensions. A package is a directory that groups related modules. Historically a package required an init.py file, which runs on import and defines the package namespace. Since Python 3.3, PEP 420 introduced namespace packages, which are directories without init.py that can be split across multiple locations on sys.path. The distinction matters for import syntax: importing a module runs its top-level code once and caches it in sys.modules. Importing a package runs its init.py and exposes its submodules and subpackages. A package can contain subpackages, forming a hierarchy. In practice, you choose a module for a small self-contained unit and a package when you need a namespace, submodules, or distribution as a single installable unit.
Module: a single file such as utils.py. Import with import utils or from utils import helper.
Regular package: a directory with init.py, for example mypkg/init.py. Submodules are mypkg.core, mypkg.io.
Namespace package: a directory without init.py. Useful for splitting a namespace across distributions.
init.py runs on import and can define all, version, and package-level initialization.
Trade-off: packages add structure and namespacing but require careful init.py design to avoid slow imports or import side effects.
Common mistake: assuming a directory is importable without init.py. In Python 2 it was not a package; in Python 3 it becomes a namespace package only if no regular package or module shadows it.
Common mistake: putting heavy imports or side effects in init.py, which slows every import of any submodule.
Version note: PEP 420 namespace packages are Python 3.3+. Regular packages with init.py work in all versions and remain the explicit choice for most projects.
0-2 years experience
2-5 years experience
5-8 years experience
8+ years experience