Python
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax and Data Types
-
Section 3: Collections
-
39: Set Operations: Union, Intersection, Difference
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Turtle Graphics and Early Practice Projects
-
Section 7: Working with Files and I/O
-
Section 8: Regular Expressions
-
Section 9: Object-Oriented Python
-
Section 10: Error Handling
-
Section 11: Modules and Packages
-
Section 12: Iterators, Generators, and Functional Tools
-
Section 13: Decorators and Metaprogramming
-
Section 14: Concurrency and Parallelism
-
Section 15: Working with Dates, Times, and Numbers
-
Section 16: Standard Library Deep Dive I: Data Structures
-
Section 17: Standard Library Deep Dive II: System and Introspection
-
Section 18: Standard Library Deep Dive III: Security and Encoding
-
Section 19: Standard Library Deep Dive IV: Text and Data Utilities
-
Section 20: Networking and Web Basics
-
Section 21: Working with Databases
-
Section 22: Testing and Quality
-
Section 23: Advanced Typing
-
Section 24: Context Managers and Resource Handling
-
Section 25: Text, Unicode, and Binary Data
-
Section 26: More Functional and Iteration Tools
-
Section 27: Data Validation and Configuration
-
Section 28: Working with Images and Media
-
Section 29: Property-Based and Documentation Testing
-
Section 30: Packaging and Deployment
-
Section 31: Performance and Internals
-
Section 32: Design Patterns in Python
-
Section 33: GUI Programming
-
Section 34: Security Basics
-
Section 35: Data Structures and Algorithms
-
Section 36: Practical Projects
-
Section 37: Capstone Projects
-
Section 38: Interview and Algorithm Practice
-
Section 39: Writing Idiomatic Python
160: Relative vs Absolute Imports
Imagine you're giving someone directions to a specific office in a massive corporate skyscraper. You have two ways to do it. You could give them the absolute address: "Go to the 12th floor, Suite 1205." It doesn't matter if they're currently in the lobby or the basement; those directions always lead to the same door. Or, you could give them relative directions: "Go up two floors and take the first door on the right." Now, those directions only work if the person is already standing on the 10th floor. If they're in the lobby, they'll end up in the wrong place entirely.
In Python, imports work exactly like this. An absolute import is the "Suite 1205" approach—it starts from the project root. A relative import is the "two floors up" approach—it depends entirely on where the current file sits in the folder hierarchy.
The "Full Address" Approach
Absolute imports are the gold standard. They specify the complete path from the project's root directory. Let's say we're building a simple e-commerce system with this structure:
ecommerce/
├── main.py
└── store/
├── __init__.py
├── orders.py
└── payments/
├── __init__.py
└── stripe_gateway.py
If I'm writing code inside stripe_gateway.py and I need a class from orders.py, an absolute import looks like this:
from store.orders import Order
I love absolute imports because they are explicit. If I move stripe_gateway.py to a different folder later, I only have to update the import if the store.orders path itself changes. It's clear, it's readable, and it's what PEP 8 (the Python style guide) generally recommends.
Navigating by Landmarks
Relative imports use leading dots to indicate how many levels "up" to go. A single dot . means "current package," and two dots .. mean "parent package."
Back in our stripe_gateway.py file, since it's inside the payments folder, and orders.py is one level up in the store folder, I can do this:
from ..orders import Order
This is handy when you're building a massive library with dozens of sub-packages. If you decide to rename the top-level store folder to shop, you don't have to go through fifty files and change from store... to from shop.... The relative import just keeps working because the "landmark" (one level up) hasn't changed.
Where things usually break
Here is the part where most developers pull their hair out: relative imports do not work if you run the script containing them directly.
If you open your terminal and run python store/payments/stripe_gateway.py, Python treats that file as the "top-level script." In its mind, there is no "parent package" because you told it that stripe_gateway.py is the starting point. You'll get a ImportError: attempted relative import with no known parent package.
I've seen this trip up even senior devs. The rule of thumb is: use relative imports for internal package organization, but always execute your code from a main entry point (like main.py) at the root of your project. That way, Python understands the full package hierarchy and knows exactly where those "dots" are leading.
📋 Practical Task
Fixing the Broken Invoice Generator Import
You've inherited a project for a billing system, but the developer who wrote it left it in a broken state. The project structure is as follows:
billing_system/
├── run.py
└── core/
├── __init__.py
├── calculator.py
└── reports/
├── __init__.py
└── invoice_gen.py
Inside invoice_gen.py, there is a line attempting to import a function called calculate_tax from calculator.py, but it's currently written as:
from calculator import calculate_tax
This is failing because calculator.py is not in the same folder as invoice_gen.py.
Your Task:
- Rewrite the import statement in
invoice_gen.pyusing a relative import to correctly referencecalculator.py. - Rewrite the same import statement using an absolute import (starting from the
corepackage). - Briefly explain why running
python core/reports/invoice_gen.pydirectly would still cause an error even after you fix the import.
There are no comments for now.