Python › Magic Methods & Operator Overloading

How do context manager magic methods __enter__ and __exit__ work, and what does __exit__'s return value control?

Advanced

Answer

__enter__(self) runs at the start of a with block and its return value is bound to the as target. __exit__(self, exc_type, exc_val, exc_tb) runs on block exit, receiving exception info if one occurred; returning True suppresses the exception, while returning False (or None) lets it propagate normally.
class Transaction:
    def __enter__(self):
        print('BEGIN')
        return self
    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_type:
            print('ROLLBACK')
            return False
        print('COMMIT')

with Transaction():
    print('doing work')
Real-world example A database Transaction class uses __enter__/__exit__ to automatically COMMIT on success and ROLLBACK if any exception occurs inside the with block, without repeating try/finally everywhere.

Common follow-ups: How does contextlib.contextmanager simplify writing this?;What happens if __exit__ itself raises an exception?