Skip to content

Instantly share code, notes, and snippets.

@lemon24
Created October 30, 2016 12:49
Show Gist options
  • Save lemon24/0857739c23a296f2741f875b52d10bca to your computer and use it in GitHub Desktop.
Save lemon24/0857739c23a296f2741f875b52d10bca to your computer and use it in GitHub Desktop.
Shows how the with statement / context managers are semantically equivalent with a try-except-finally block.
"""
Shows how the with statement / context managers are semantically equivalent
with a try-except-finally block.
https://docs.python.org/3/reference/compound_stmts.html#the-try-statement
https://docs.python.org/3/reference/simple_stmts.html#the-raise-statement
https://docs.python.org/3/reference/compound_stmts.html#the-with-statement
https://docs.python.org/3/reference/datamodel.html#with-statement-context-managers
https://docs.python.org/3.7/library/sys.html#sys.exc_info
"""
import sys
def using_try_except_finally():
"""What you did before context managers."""
print('before')
try:
v = 'during'
print(v)
raise ValueError('error from try except')
except Exception as e:
print(e)
raise
finally:
print('after')
class ContextManager:
"""Useful if at least one of the before, during or after parts
are reusable.
"""
def __enter__(self):
print('before')
return 'during'
def __exit__(self, exc_type, exc_value, traceback):
if exc_value:
print(exc_value)
print('after')
def using_context_managers():
"""What you do with context managers."""
cm = ContextManager()
with cm as v:
print(v)
raise ValueError('error from with')
def using_context_managers_manually():
"""What the interpreter does when you use context managers."""
cm = ContextManager()
exc_info = None
v = cm.__enter__()
try:
print(v)
raise ValueError('error from magic')
except Exception as e:
exc_info = sys.exc_info()
finally:
if not cm.__exit__(*exc_info):
if exc_info:
exc_type, exc_value, traceback = exc_info
raise exc_value
functions = [
using_try_except_finally,
using_context_managers,
using_context_managers_manually,
]
for f in functions:
try:
print('# calling', f.__name__)
f()
except Exception as e:
print('# caught exception:', e)
print()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment