I have the following code:
class Test: def __init__(self, name): self.name = name def __enter__(self): print(f'entering {self.name}') def __exit__(self, exctype, excinst, exctb) -> bool: print(f'exiting {self.name}') return True with Test('first') as test: print(f'in {test.name}') test = Test('second') with test: print(f'in {test.name}')
Running it produces the following output:
entering first exiting first entering second in second exiting second
But I expected it to produce:
entering first in first exiting first entering second in second exiting second
Why isn't the code within my first example called?
The problem is that your __enter__
method returns None
. Hence, test
is assigned None
.
Then you try to access (None).name
, which raises an error. Since your __exit__
method returns True
always, it will suppress any errors. According to the docs:
Returning a true value from this method will cause the with statement to suppress the exception and continue execution with the statement immediately following the with statement.
The __enter__
method should return the context object. with ... as ...
uses the return value of __enter__
to determine what object to give you. Since your __enter__
returns nothing, it implicitly returns None
, so test
is None
.
with Test('first') as test: print(f'in {test.name}') test = Test('second') with test: print(f'in {test.name}')
So test
is none. Then test.name
is an error. That error gets raised, so Test('first').__exit__
gets called. __exit__
returns True
, which indicates that the error has been handled (essentially, that your __exit__
is acting like an except
block), so the code continues after the first with
block, since you told Python everything was fine.
Consider
def __enter__(self): print(f'entering {self.name}') return self
You might also consider not returning True
from __exit__
unless you truly intend to unconditionally suppress all errors in the block (and fully understand the consequences of suppressing other programmers' errors, as well as KeyboardInterrupt
, StopIteration
, and various system signals)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With