else runs when no exception occurred; finally always runs regardless of outcome
A try statement can have up to four blocks: try, except, else, and finally. The else block runs only if the try block completed without raising, which lets you separate the code that might fail from the code that should only run on success, and it prevents the except clause from accidentally catching errors raised by your success path. The finally block always runs, whether the try succeeded, raised a handled exception, raised an unhandled exception, or executed a return, break, or continue. It is the right place for cleanup, and it is the mechanism context managers use internally.
else runs once, after try succeeds, before finally.
finally always runs, even on return, break, continue, or an exception that is propagating.
Order: try -> except (if raised) -> else (if not raised) -> finally (always).
return inside finally overrides any return from try or except. That is almost always a bug.
Trade-off: with statements are usually a better cleanup mechanism than try/finally, but finally is still needed when the resource is not a context manager.
Common mistake: putting success-only logic inside try, which causes the except clause to catch bugs in the success path and mask them.
Version note: try/except/else/finally has been stable since Python 2.5, when finally and except were merged into one statement.
0-2 years experience
2-5 years experience
5-8 years experience
8+ years experience