JV
PY

Java to Python

10 lessons

Progress0%
1Variables & Types2Classes & OOP3Collections4Exception Handling5File I/O6Functional Programming7Duck Typing and Protocols8Python Ecosystem9Type Hints and Static Analysis10Context Managers and Resources
All Mirror Courses
JV
PY
Context Managers and Resources
MirrorLesson 10 of 10
Lesson 10

Context Managers and Resources

Python's with statement and __enter__/__exit__ protocol replaces Java's try-with-resources and AutoCloseable for deterministic resource cleanup.

Introduction

In this lesson, you'll learn about context managers and resources in Python. Coming from Java, you already have a foundation for understanding this concept. We'll build on that knowledge while highlighting the key differences.

Mirror Card
JV
From Java:

In Java, you're familiar with python's with statement and __enter__/__exit__ protocol replaces java's try-with-resources and autocloseable for deterministic resource cleanup..

PY
In Python:

Python has its own approach to python's with statement and __enter__/__exit__ protocol replaces java's try-with-resources and autocloseable for deterministic resource cleanup., which we'll explore step by step.

The Python Way

Let's see how Python handles this concept. Here's a typical example:

PY
Python Example
from contextlib import contextmanager
import threading

# Built-in: files, locks, database connections
with open("file.txt") as f:          # __exit__ closes file
    for line in f:
        print(line, end="")

# Multiple resources in one with
with open("src.txt") as src, open("dst.txt", "w") as dst:
    dst.write(src.read())

# Custom context manager: __enter__ and __exit__
class Timer:
    import time
    def __enter__(self):
        self._start = self.time.monotonic()
        return self          # value bound by 'as'

    def __exit__(self, exc_type, exc_val, exc_tb):
        elapsed = self.time.monotonic() - self._start
        print(f"Elapsed: {elapsed:.3f}s")
        return False  # don't suppress exceptions

with Timer() as t:
    sum(range(10_000_000))

# @contextmanager: generator-based shorthand
@contextmanager
def managed_connection(dsn: str):
    conn = connect(dsn)   # __enter__
    try:
        yield conn         # body of 'with' block runs here
    finally:
        conn.close()       # __exit__

with managed_connection("db.sqlite3") as conn:
    conn.execute("SELECT 1")

Comparing to Java

Here's how you might have written similar code in Java:

JV
Java (What you know)
import java.io.*;
import java.sql.*;

public class Resources {
    // AutoCloseable: close() called automatically
    void readFile(String path) throws IOException {
        try (var reader = new BufferedReader(new FileReader(path))) {
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
        } // reader.close() called here, even on exception
    }

    // Multiple resources in one try-with-resources
    void copy(String src, String dst) throws IOException {
        try (var in  = new FileInputStream(src);
             var out = new FileOutputStream(dst)) {
            in.transferTo(out);
        }
    }
}
Mirror Card
JV
From Java:

You may be used to different syntax or behavior.

PY
In Python:

with open(...) is Python's try-with-resources — __exit__ is called even if an exception is raised

Mirror Card
JV
From Java:

You may be used to different syntax or behavior.

PY
In Python:

Any class with __enter__/__exit__ is a context manager; Java requires implementing AutoCloseable

Mirror Card
JV
From Java:

You may be used to different syntax or behavior.

PY
In Python:

@contextmanager turns a generator into a context manager — yield is the 'with body'; try/finally is cleanup

Mirror Card
JV
From Java:

You may be used to different syntax or behavior.

PY
In Python:

Multiple resources in one 'with' are handled left-to-right on enter, right-to-left on exit

Mirror Card
JV
From Java:

You may be used to different syntax or behavior.

PY
In Python:

__exit__(type, val, tb) receives exception info; returning True suppresses the exception

Step-by-Step Breakdown

1. with Statement

'with expr as var' calls __enter__ and binds the result to var; __exit__ is called on block exit regardless of exceptions.

JV
Java
try (var f = new BufferedReader(...)) { ... }
PY
Python
with open("data.txt", "r") as f:
    content = f.read()
# f is closed here, even if an exception was raised

2. Multiple Resources

Comma-separated 'with' handles multiple resources. Each is entered left-to-right and exited right-to-left — same as nested with blocks.

JV
Java
try (var in = new FileInputStream(s);
     var out = new FileOutputStream(d)) { ... }
PY
Python
with open(src) as fin, open(dst, "w") as fout:
    fout.write(fin.read())
# Both files closed; fout closed before fin

3. Custom Context Manager

__enter__ sets up the resource; __exit__ tears it down. Implement both methods on any class to make it a context manager.

JV
Java
class MyRes implements AutoCloseable {
    public void close() { ... }
}
PY
Python
class Lock:
    def __enter__(self):
        acquire()
        return self
    def __exit__(self, *args):
        release()
        return False  # don't suppress exceptions

4. @contextmanager Decorator

Write setup before yield and cleanup in finally. The yield is where the with-block body executes.

JV
Java
// Java: must implement AutoCloseable class
PY
Python
from contextlib import contextmanager

@contextmanager
def timer(label: str):
    import time
    start = time.monotonic()
    try:
        yield          # with-block runs here
    finally:
        print(f"{label}: {time.monotonic()-start:.3f}s")

with timer("sort"):
    sorted(range(100_000))
Rule of Thumb
Use @contextmanager for simple cases; implement __enter__/__exit__ when the class needs to be a context manager and also do other work.

Common Mistakes

When coming from Java, developers often make these mistakes:

  • with open(...) is Python's try-with-resources — __exit__ is called even if an exception is raised
  • Any class with __enter__/__exit__ is a context manager; Java requires implementing AutoCloseable
  • @contextmanager turns a generator into a context manager — yield is the 'with body'; try/finally is cleanup
Common Pitfall
Don't assume Python works exactly like Java. While the concepts may be similar, the syntax and behavior can differ significantly.

Key Takeaways

  • with open(...) as f: auto-closes on exit — Python's equivalent of try-with-resources
  • Implement __enter__/__exit__ on any class to make it a context manager
  • @contextmanager: yield separates setup from teardown; cleanup goes in finally block
  • Multiple resources: with a() as x, b() as y — entered left-to-right, exited right-to-left
Rule of Thumb
The best way to learn is by doing. Try rewriting some of your Java code in Python to practice these concepts.
PreviousFinish