Skip to content

CONTEXT MANAGERS - Using 'with' statement for automatic file closing

Python
#!/usr/bin/env python3
"""
CONTEXT MANAGERS - Using 'with' statement for automatic file closing
Demonstrates the recommended way to handle files in Python
"""

import os
import tempfile

print("=" * 60)
print("CONTEXT MANAGERS - Automatic File Closing")
print("=" * 60)

temp_dir = tempfile.gettempdir()

# Example 1: Without context manager (old way)
print("\n1. Without Context Manager (Manual Close)")
print("-" * 40)
file1 = os.path.join(temp_dir, "old_way.txt")

f = open(file1, 'w')
f.write("Must remember to close manually\n")
f.close()  # Easy to forget!

f = open(file1, 'r')
content = f.read()
f.close()  # Easy to forget!
print("Content:", content)

# Example 2: With context manager (recommended)
print("\n2. With Context Manager (Automatic Close)")
print("-" * 40)
file2 = os.path.join(temp_dir, "new_way.txt")

with open(file2, 'w') as f:
    f.write("Automatically closed when block ends\n")
# File is automatically closed here!

with open(file2, 'r') as f:
    content = f.read()
# File is automatically closed here!
print("Content:", content)

# Example 3: Exception handling benefit
print("\n3. Automatic Close Even on Errors")
print("-" * 40)
file3 = os.path.join(temp_dir, "error_test.txt")

try:
    with open(file3, 'w') as f:
        f.write("Start writing\n")
        # Simulate an error
        result = 10 / 0  # This will cause ZeroDivisionError
        f.write("This won't execute\n")
except ZeroDivisionError:
    print("Error occurred, but file was still closed properly!")

# Verify file was written and closed
with open(file3, 'r') as f:
    print("File content:", f.read())

# Example 4: Multiple files at once
print("\n4. Opening Multiple Files Simultaneously")
print("-" * 40)
source = os.path.join(temp_dir, "source.txt")
dest = os.path.join(temp_dir, "destination.txt")

# Create source file
with open(source, 'w') as f:
    f.write("Copy this content\n")

# Open both files at once
with open(source, 'r') as src, open(dest, 'w') as dst:
    content = src.read()
    dst.write(content)
    print("Copied content from source to destination")

# Verify
with open(dest, 'r') as f:
    print("Destination content:", f.read())

# Example 5: Nested operations
print("\n5. Reading and Processing Line by Line")
print("-" * 40)
data_file = os.path.join(temp_dir, "numbers.txt")

# Write test data
with open(data_file, 'w') as f:
    for i in range(1, 6):
        f.write(f"{i}\n")

# Read and process
total = 0
with open(data_file, 'r') as f:
    for line in f:
        number = int(line.strip())
        total += number
        print(f"Read: {number}, Running total: {total}")

# Example 6: File context is maintained
print("\n6. File Object Available in Entire Block")
print("-" * 40)
test_file = os.path.join(temp_dir, "test.txt")

with open(test_file, 'w') as f:
    print(f"File is open: {not f.closed}")
    f.write("Line 1\n")
    print(f"Still open: {not f.closed}")
    f.write("Line 2\n")
    print(f"Still open: {not f.closed}")

print(f"Outside block, file closed: {f.closed}")

# Cleanup
for f in [file1, file2, file3, source, dest, data_file, test_file]:
    if os.path.exists(f):
        os.remove(f)

print("\n" + "=" * 60)
print("Key Points:")
print("  - 'with' statement automatically closes files")
print("  - Works even if exceptions occur")
print("  - Cleaner and more readable code")
print("  - Can open multiple files in one 'with'")
print("  - ALWAYS use 'with' for file operations")
print("=" * 60)