Module Scope and Namespaces
An import statement tells Python to find a module file, execute its code, and make its contents available to your program.
Importing Is a Process
An import statement is more than a request to use a name. It instructs Python to locate a module, load it, execute the code in the module, and make the module's contents available to the importing program. This search-and-execute process happens behind the scenes whenever a module is imported.
Following sys.path
For a module that is not built into Python, the interpreter searches directories listed in sys.path. Python checks those directories in a specific order. It stops at the first directory containing a matching module file and uses that file. The search therefore depends not only on which files exist, but also on where those files appear in the search order.
A Search-Order Example
Suppose a program requests a non-built-in module named reports, and two directories in sys.path contain a matching module file.
First directory: Python checks the first directory in the relevant search order.
First match: If that directory contains the requested module file, Python uses it immediately.
Later directory: Python does not continue searching for another matching file after the first match.
The directory order in sys.path determines which matching module file is selected.
First Import and Later Imports
When Python finds a module, it executes the code in that module's body during initialization. Python then caches the loaded module in memory. If the same module is imported again later, Python returns the cached module instead of executing the module's initialization code again.
One Initialization, Multiple Imports
A program imports the same module twice during its execution.
First import: Python locates the module, executes its code, and caches the loaded module.
Second import: Python finds that the module is already loaded and reuses the cached module.
Observed behavior: The module's initialization code is not executed a second time.
The module is initialized once, while later imports use the already loaded module.
Contents Inside a Module
A module provides a separate place for its contents. Importing makes those contents available to the program that performed the import. This separation is the useful idea behind module scope and namespaces: module-related names and definitions are associated with the module that supplies them, rather than being treated as if they were newly declared directly in every importing location.
Naming Conflicts
Assuming Python can find every module without searching
For non-built-in modules, Python searches directories listed in sys.path and uses the first matching file.
Fix:
Think of import as a locate, load, execute, and make-available process.Expecting a repeated import to reinitialize a module
Python caches the module after its first import and reuses it on later imports.
Fix:
Expect the module to be initialized once and its state to persist during the program's execution.Ignoring the order of sys.path
Depending on search-path order, Python might find the locally created file instead of the intended module.
Fix:
Use distinctive names and remember that the first matching location wins.
When debugging an import-related problem, inspect the search path and consider every directory Python checks before the module you expected. Search order can explain why a module with an unexpected name or location was selected.
Practice the Trace
A non-built-in module is requested. The first directory in sys.path does not contain a matching file, but the second directory does. Explain which directory Python uses, whether it checks later directories, and what happens if the same module is imported again later.
Hints
- Follow the directories in sys.path in order.
- The first matching file ends the search.
- Separate the first import from later imports.
- An import statement starts a locate-and-load process. For non-built-in modules, Python searches sys.path in order and stops at the first matching module file. The first import executes the module's initialization code and caches the loaded module. Later imports reuse that cached module without re-executing its code. The module's contents are kept associated with the module and made available to the importing program.
Key Takeaways
- Importing a module triggers a locate, load, execute, and availability process.
- Python searches sys.path in order for non-built-in modules and uses the first matching file.
- A module's initialization code runs only during its first import.
- Later imports reuse the cached module, allowing module state to persist during the program's execution.
- Search-path order can cause naming conflicts when different files have the same module name.