1.The with statement
with obj: runs obj.__enter__() before the block and obj.__exit__() after — even if the block raises. It replaces a manual try/finally for setup and teardown.
Key features
- with obj as name: calls obj.__enter__() first; its return value becomes name
- obj.__exit__() runs when the block ends — on normal completion AND on exception
- Removes the need to write try/finally by hand for setup/teardown pairs
- name is optional — with obj: is valid if the return value of __enter__ is not needed
- Any object implementing __enter__ and __exit__ works — the protocol, not a base class
Manual try/finally vs with, for the same guarantee
- __enter__() — setup — return value becomes as name
- block body — may complete, or raise
- __exit__() — teardown — always runs
Command
with expression as name:
# name is expression.__enter__()'s return value
...
# expression.__exit__() has already run by here, alwayswith obj as name: runs __enter__ before the block and __exit__ after — even on an exception. It is try/finally you do not have to write.