with StatementIntroduction π
A Context Manager in Python is a special tool that helps you manage resources (like files, database connections, network sockets, locks) efficiently. The with statement ensures that resources are properly cleaned up β even if an error occurs.
Note
βDo something before a block runs, and clean up afterward.β
1. Basic Example of with Statement π
with_file.py
with open("data.txt", "r") as file:
content = file.read()
print(content)β File is automatically closed after block
β No need to call file.close()
2. How Context Managers Work Internally π§©
Any object that works with with must implement two methods:
- __enter__() β runs before block
- __exit__() β runs after block (even if errors occur)
3. Creating Your Own Context Manager (Class-Based) ποΈ
class_context_manager.py
class MyContext:
def __enter__(self):
print("Entering context...")
return "Resource Ready"
def __exit__(self, exc_type, exc_val, exc_tb):
print("Exiting context...")
print("Cleaning up resources")
return False # Do NOT suppress exceptions
with MyContext() as resource:
print(resource)β __enter__ returns the object used inside with
β __exit__ is guaranteed to run
4. Handling Exceptions Inside Context Managers β οΈ
context_exception.py
class Demo:
def __enter__(self):
print("Start")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("End")
return True # suppress exceptions
with Demo():
raise ValueError("Something went wrong!")β Returning True from __exit__() prevents the exception from propagating.
5. Creating a Context Manager Using contextlib (Decorator Style) π
This is easier and more readable than writing a class.
contextlib_manager.py
from contextlib import contextmanager
@contextmanager
def my_manager():
print("Before block")
yield "Hello"
print("After block")
with my_manager() as msg:
print(msg)β yield splits the setup and teardown logic.
6. Real-World Example: Opening Files π
file_manager.py
with open("log.txt", "a") as log:
log.write("New activity added\n")β Automatically closes file
β Prevents memory leaks
7. Real-World Example: Database Connection π
db_manager.py
class DB:
def __enter__(self):
print("Connecting to DB...")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("Closing DB connection...")
with DB():
print("Querying DB...")8. Real-World Example: Timer Context Manager β³
timer_context.py
import time
class Timer:
def __enter__(self):
self.start = time.time()
return self
def __exit__(self, *args):
print("Elapsed:", time.time() - self.start)
with Timer():
for _ in range(1000000):
pass9. Real-World Example: Temporary Directory (contextlib) π
temp_dir.py
from contextlib import TemporaryDirectory
with TemporaryDirectory() as temp_dir:
print("Temp folder created:", temp_dir)
# folder auto-deletes after block10. Nested Context Managers π
nested_contexts.py
with open("a.txt") as f1, open("b.txt") as f2:
print(f1.read(), f2.read())β Clean & readable syntax.
11. Using Context Managers in Classes π―
class_usage.py
class Writer:
def __init__(self, filename):
self.filename = filename
def __enter__(self):
self.file = open(self.filename, "w")
return self.file
def __exit__(self, *args):
self.file.close()
with Writer("msg.txt") as f:
f.write("Hello!")12. Best Practices π‘
- β Always use with open() for file handling
- β Use contextlib for simple custom managers
- β Do not suppress exceptions unless necessary
- β Keep setup in __enter__ and cleanup in __exit__
- β Use context managers for any resource cleanup
Conclusion π
You now fully understand Context Managers & the with Statement in Python! Want the next topic? Try JSON Handling, CSV Files, OOP (Classes), or Exception Hierarchy. Just tell me! π