Understanding Python's with Statement and Context Managers with Practical Examples
This article explains Python's with statement as a context management tool, describes the required __enter__ and __exit__ methods, and provides multiple practical examples—including file handling, custom managers, multiple managers, third‑party resources, and automation scenarios—to illustrate reliable resource acquisition and cleanup.
In Python, the with statement is a context management tool used to ensure that resources are properly acquired and released, even when exceptions occur, making it ideal for tasks such as file handling, locking, and network connections.
To use with , a class must implement the context manager protocol by defining __enter__() and __exit__() methods. __enter__() prepares the resource and optionally returns an object for the as clause, while __exit__() handles cleanup and receives exception information.
Example 1: File operation
with open('example.txt', 'r') as file:
content = file.read()
print(content)Example 2: Custom context manager
class ManagedResource:
def __enter__(self):
print("Initializing resource...")
# initialize resource
return self # return manager or other object
def __exit__(self, exc_type, exc_val, exc_tb):
print("Cleaning up resource...")
# clean up resource
if exc_type is not None:
print(f"An exception of type {exc_type} occurred.")
return False # do not suppress exceptions
with ManagedResource() as resource:
print("Using resource...")
raise ValueError("An error occurred!")Example 3: Multiple context managers
with open('file1.txt', 'w') as file1, open('file2.txt', 'w') as file2:
file1.write("Hello, world!\n")
file2.write("Goodbye, world!")Example 4: Using a third‑party library (threading.Lock)
import threading
lock = threading.Lock()
with lock:
# critical section code
print("Critical section executed.")Example 5: Simplifying with contextlib
import contextlib
@contextlib.contextmanager
def managed_resource():
print("Initializing resource...")
try:
yield "resource" # return resource
finally:
print("Cleaning up resource...")
with managed_resource() as res:
print(f"Using resource: {res}")Advanced examples for API automation
Using with to manage a requests session ensures the session is closed after use.
import requests
def test_session_with_auth():
url = "https://api.example.com/data"
headers = {"Authorization": "Bearer your_token"}
with requests.Session() as session:
session.headers.update(headers)
response = session.get(url)
assert response.status_code == 200
assert "data" in response.json()Managing temporary files with with guarantees they are closed and can be deleted.
import tempfile, json, os
def test_upload_file():
data = {"key": "value"}
with tempfile.NamedTemporaryFile(mode='w+', delete=False) as tmp:
tmp.write(json.dumps(data))
filename = tmp.name
url = "https://api.example.com/upload"
files = {'file': open(filename, 'rb')}
with requests.post(url, files=files) as response:
assert response.status_code == 200
os.remove(filename)Using with for a SQLite connection ensures the database is properly closed.
import sqlite3
def test_database_query():
db_file = 'test.db'
query = 'SELECT * FROM users WHERE id = ?'
with sqlite3.connect(db_file) as conn:
cursor = conn.cursor()
cursor.execute(query, (1,))
result = cursor.fetchall()
assert len(result) == 1Managing environment variables within a with block (illustrative example) restores the original state after the block.
import os
def test_environment_variable():
original_value = os.getenv('TEST_VAR')
with os.environ['TEST_VAR'] = 'test_value':
assert os.getenv('TEST_VAR') == 'test_value'
assert os.getenv('TEST_VAR') == original_valueUsing a lock in multithreaded tests with with guarantees the lock is released.
import threading
def test_thread_lock():
lock = threading.Lock()
shared_data = []
def worker():
with lock:
shared_data.append(threading.current_thread().ident)
threads = [threading.Thread(target=worker) for _ in range(5)]
for t in threads:
t.start()
for t in threads:
t.join()
assert len(shared_data) == 5Summary
These examples demonstrate how the with statement can be employed in API automation testing and general Python programming to manage sessions, files, database connections, environment variables, and locks, ensuring proper initialization and cleanup of resources for more reliable and efficient code.
Test Development Learning Exchange
Test Development Learning Exchange
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.