Modules and Packages
Modules and Packages
A module is simply a .py file; a package is a directory containing an __init__.py (in classic layouts) and submodules. Candidates must know the import machinery: import x binds the module object x in the current namespace, while from x import y binds the object y directly. from x import * respects __all__ if defined, otherwise imports all names not starting with underscore.
Key concepts: the module search path (sys.path, current directory first, then PYTHONPATH, then installation directories), sys.modules caching (a module body executes only once per interpreter session), relative imports (from . import sibling) which only work inside packages, and the if __name__ == "__main__": guard, since __name__ is "__main__" only for the directly executed script.
Traps: questions often show a package with an __init__.py that imports a submodule, then ask what attribute exists after import package. Another classic: from module import name creates a snapshot binding, so rebinding the module-level name later does not update the imported reference. Circular imports and shadowing built-ins (naming a file random.py) also appear. Remember that importing a package executes its __init__.py.
Worked example: given pkg/__init__.py containing from .sub import helper, executing import pkg makes pkg.helper available without import pkg.sub, because the __init__ ran the relative import. Rule of thumb: import binds the module, from ... import binds the object; the module body runs once, cached in sys.modules.