Modules & Packages
Importing Modules
import, from, as statements for using external code
Interview: Common interview topic — circular imports and import styles are frequently discussed
Python's import system allows you to use code from other files and libraries. Understanding import styles, module resolution, and best practices is essential for writing well-organized Python programs and is frequently tested in interviews.
Import Styles
- import module:
import os— access viaos.path(recommended for clarity) - from module import name:
from os import path— access directly aspath - import module as alias:
import numpy as np— standard convention for common libraries - from module import *:
from math import *— imports all public names; AVOID in production code
Import Resolution Order
- Built-in modules: Checked first (sys, os, math)
- sys.path directories: Current directory, then PYTHONPATH, then standard library paths
- Installed packages: From site-packages (pip-installed packages)
Avoid Wildcard Imports
from module import * pollutes the namespace, makes it unclear where names come from, and can override built-in functions. Always use explicit imports. PEP 8 allows it only in interactive shells and __init__.py for re-exporting.
Circular Imports
When module A imports module B, and module B imports module A, you get a circular import. Python handles this partially (the module exists but may be incomplete), but it causes subtle bugs. Solutions: restructure code, use local imports inside functions, or merge the modules.
PEP 8 Import Rules
Imports should be at the top of the file, grouped in this order: (1) standard library, (2) third-party, (3) local. Each group separated by a blank line. Use one import per line for clarity.
Use Cases
Organizing code across multiple files with clean import patterns
Using standard library and third-party packages effectively
Lazy loading optional dependencies with try/except ImportError
Building package APIs with __init__.py re-exports
Avoiding circular dependencies in large codebases
Common Mistakes
Using from module import * — pollutes namespace, hides name origins, can override builtins
Not following PEP 8 import ordering — makes code harder to scan
Ignoring circular imports — causes incomplete module loading and subtle bugs
Importing at function level when top-level import would work — unnecessary complexity
Forgetting that imports are executed only once — module-level code runs on first import