I’m a bit new to Python still, and I got a question about the nuances of “with X as Y” in Python. It seems to be similar to a try-with-resources in Java, but I’m wondering what the differences are (so I don’t make assumptions). So, what are the differences between the following two:
try (InputStream in = getInput()) {
// Java -- Do stuff
}
and
with getInput() as source:
# Python -- Do stuff
0
One difference in semantics is that with the following Java block:
try (InputStream in = getInput()) {
// Java -- Do stuff
}
...
InputStream in2 = getInput();
assert(in2.getClass() == in.getClass());
the variable in
has the actual value returned by getInput()
. But with Python, this is not necessarily the case:
with getInput() as source:
# Python -- Do stuff
...
source2 = getInput()
# Now source and source2 are not necessarily the same type
Here, getInput()
returns an object that has a method called __enter__()
. The variable source
is then assigned whatever value __enter()__
returns. It is a very common practice for __enter()__
to return self
in order to avoid surprises, but it’s not an actual requirement.
2
The with
statement is more general than the try-with-resources statement. A with
statement is a general framework that can be used to invoke arbitrary code on entry to and on exit from the body of the with
statement. It does this by using a context manager, which is any object with appropriately defined __enter__
and __exit__
methods. As a very simple example:
class Foo:
def __enter__(self):
print("Entering")
return 9
def __exit__(self, *args):
print("Exiting")
f = Foo()
with f as x:
print(x)
will output
Entering
9
Exiting
just as if you had written
f = Foo()
x = f.__enter__()
print(x)
f.__exit__()
(For simplicity, I’m ignoring exception handling. Information about any exception raised in the body of the with
statement is passed to the __exit__
method for possibly handling and/or re-raising.)
See https://docs.python.org/3/reference/compound_stmts.html#with for a more complete description of what an arbitrary with
statement “desugars” to.
1