The problem
You need to ensure resources are properly cleaned up, even if errors occur.
The solution
from contextlib import contextmanager
import time
@contextmanager
def timer(name="Operation"):
"""Context manager to time code execution."""
start = time.perf_counter()
try:
yield
finally:
elapsed = time.perf_counter() - start
print(f"{name} took {elapsed:.4f} seconds")
@contextmanager
def temp_file(filename, mode='w'):
"""Context manager for temporary file operations."""
import os
try:
f = open(filename, mode)
yield f
finally:
f.close()
if os.path.exists(filename):
os.remove(filename)Put it to work
# Time a block of code
with timer("Data processing"):
# Your code here
data = [x ** 2 for x in range(1000000)]
# Output: Data processing took 0.0823 seconds
# Work with temporary file
with temp_file('temp.txt') as f:
f.write('temporary data')
# File is automatically deleted afterWorth knowing
The yield statement is where the with block code runs. Use try/finally to ensure cleanup even on errors.