In [2]:
class Context(object):
def __init(self):
print('__init__')
def __enter__(self):
print('__enter__')
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print('__exit__')
with Context():
print('Do working in the context')
In [3]:
class WithinContext:
def __init__(self, context):
print('WithinContext.__init__({})'.format(context))
def do_something(self):
print('WithinContext.do_something()')
def __del__(self):
print('WithinContext.__del__')
class Context:
def __init__(self):
print('Context.__init__()')
def __enter__(self):
print('Context.__enter__()')
return WithinContext(self)
def __exit__(self, exc_type, exc_val, exc_tb):
print('Context.__exit__()')
with Context() as c:
c.do_something()
Exception rasied
In [4]:
class Context:
def __init__(self, handle_error):
print('__init__({})'.format(handle_error))
self.handle_error = handle_error
def __enter__(self):
print('__enter__()')
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print('__exit__()')
print(' exc_type =', exc_type)
print(' exc_val =', exc_val)
print(' exc_tb =', exc_tb)
return self.handle_error
with Context(True):
raise RuntimeError('error message handled')
print()
with Context(False):
raise RuntimeError('error message propagated')
In [5]:
import contextlib
class Context(contextlib.ContextDecorator):
def __init__(self, how_used):
self.how_used = how_used
print('__init__({})'.format(how_used))
def __enter__(self):
print('__enter__({})'.format(self.how_used))
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print('__exit__({})'.format(self.how_used))
@Context('as decorator')
def func(message):
print(message)
print()
with Context('as context manager'):
print('Doing work in the context')
print()
func('Doing work in the wrapped function')
In [7]:
import contextlib
@contextlib.contextmanager
def make_context():
print(' entering')
try:
yield {}
except RuntimeError as err:
print(' ERROR:', err)
except ValueError as err:
print( 'ERROR:', err)
finally:
print(' exiting')
print('Normal:')
with make_context() as value:
print(' inside with statement:', value)
print('\nHandled error:')
with make_context() as value:
raise RuntimeError('showing example of handling an error')
print('\nUnhandled error:')
with make_context() as value:
raise ValueError('this exception is not handled')
In [11]:
import contextlib
class NonFatalError(Exception):
pass
def non_idempotent_operation():
raise NonFatalError(
'The operation failed because of existing state'
)
with contextlib.suppress(NonFatalError):
print('trying non-idempotent operation')
non_idempotent_operation()
print('succeeded!')
print('done')
In [ ]: