Import System
import foo searches sys.path, executes the module file once, and caches it in sys.modules. Subsequent imports return the cached version.
Importing is like microwaving a frozen dinner — it cooks (executes) the first time, then sits in sys.modules like leftovers in the fridge. Grabbing it again just opens the fridge door.
sys.path is a list of directories searched in order (current dir, PYTHONPATH, stdlib, site-packages). Packages require __init__.py (or are namespace packages in Python 3.3+). Relative imports use dots: from . import sibling, from .. import parent. __all__ controls what from module import * exports.
The import machinery uses finders and loaders (importlib). sys.meta_path contains meta path finders checked first. sys.modules is the module cache — you can hot-reload by deleting a key and re-importing. Circular imports work if you import the module (not specific names) and access names after the circular import resolves. import foo runs foo.py top-to-bottom in a new module namespace — side effects at module level execute immediately.
Python's import system finds modules via sys.path, executes them once, and caches in sys.modules — so reimporting is cheap. __init__.py makes a directory a package. Circular imports are possible but tricky — import the module, not specific names, and access them after the import cycle resolves. You can inspect the import machinery via importlib.
Modules are executed once and cached. If module A modifies global state at import time, that state is shared across all importers. Reimporting doesn't reset it — you need importlib.reload() for that.