Python Modules and the import System/shaare/XckVlw
Python Modules and the import System
What is a Module?
- A module in Python corresponds directly to a single file containing Python code.
- The module's name is derived from its filename.
- Any file with a
.pyextension can be treated as a module. - The name used to import the module is the filename without the
.pysuffix. For example, a file namedfile_ops.pyis imported as thefile_opsmodule.
The import Statement
- The most straightforward way to import a module is with
import module_name - To use functions, variables, or classes from the imported module, you must prefix them with the module name and a dot, such as
module_name.function_name. - This method creates a dedicated namespace for the imported module, which is highly effective at preventing name collisions. For instance, a variable named
CONFIGin your script will not conflict withmodule_name.CONFIG. - It enhances code clarity by making it obvious where each function or variable originates, which is especially helpful in larger projects.
The from...import Statement
- It's possible to bring only specific objects from a module with
from ... import .... - You can use the
askeyword to rename an imported object, for example,from file_ops import parse_yaml_file as parse_yaml. - This approach can make code more concise because it requires less typing (
parse_yaml()instead offile_ops.parse_yaml_file()). - The primary drawback is the increased risk of name collisions. If you import a function named
my_functionand later define your own function with the same name, the original import will be overwritten. - Using
from module import *is strongly discouraged because it imports all public names from the module, which can pollute the local namespace and make the code difficult to read and debug.
How Python Finds Modules: sys.path
When you execute an import statement, Python needs to locate the corresponding module file. It does this by searching through a specific list of directories.
- The search path is stored in a list of strings called
sys.path, which is part of the standardsysmodule. - The
sys.pathlist is automatically populated and typically includes the directory of the script that is currently running, directories specified in thePYTHONPATHenvironment variable, and the default locations where Python and third-party packages are installed. - The fact that the script's own directory is the first entry on this path is why a script like
main.pycan seamlessly importutils.pywhen both files are located in the same folder.
Example of main.py
print("Main script starting...")
from devops_utils import (
check_file_extension,
is_host_up,
check_hosts_from_config,
)
import sys
print(sys.path)
filenames = ["config.yaml", "script.sh"]
for filename in filenames:
print(f"Checking {filename}")
print(f"Result: {check_file_extension(filename)}")
print(f"\nIs localhost up? {is_host_up("localhost")}")
print(
f"Is nonexistenthost12345 up? {is_host_up("nonexistenthost12345")}"
)
print(
f"\nAre all hosts from servers_config.yaml up? {check_hosts_from_config("servers_config.yaml")}"
)
Example of file_ops.py
print("Module file_ops is being imported")
from typing import Any
try:
import yaml
except (ModuleNotFoundError, ImportError):
print(
"Warning: PyYAML not found, parse_yaml_file will not work."
)
yaml = None
SUPPORTED_EXTENSIONS: list[str] = [".json", ".yaml", ".txt"]
def check_file_extension(filename: str) -> bool:
"""Checks if a file has a supported extension"""
print(
f" - file_ops.check_file_extension called for {filename}"
)
return any(
filename.endswith(ext) for ext in SUPPORTED_EXTENSIONS
)
def parse_yaml_file(path_str: str) -> dict[str, Any]:
"""Parses a YAML file and returns its contents."""
print(f" - file_ops.parse_yaml_file called for {path_str}")
if yaml:
with open(path_str, "r") as file:
return yaml.safe_load(file)
else:
return {}
(97)