@contextmanager defexample(): l = [1, 2, 3, 4] print('start') try: yield l raise Exception('test') except: print("exception") finally: print('end')
也可以在 with 语句块之外捕获该异常:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
@contextmanager defexample(): l = [1, 2, 3, 4] print('start') try: yield l raise Exception('test') finally: print('end')
try: with example() as msg: for i in msg: print(i) except: pass
如果异常发生在 yeild 之前,则 yield 不会返回到 with 语句中,with语句块会抛出RuntimeError异常:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
@contextmanager defexample(): l = [1, 2, 3, 4] print('start') try: raise Exception('test') yield l except: print("exception") finally: print('end')
with example() as msg: for i in msg: print(i)
上面的代码会抛出如下异常:
1 2 3 4 5 6
raceback (most recent call last): File "tmp.py", line 17, in <module> with example() as msg: File "D:\software\Python36\lib\contextlib.py", line 83, in __enter__ raise RuntimeError("generator didn't yield") fromNone RuntimeError: generator didn't yield
def__exit__(self, type, value, traceback): if type isNone: try: next(self.gen) except StopIteration: returnFalse else: raise RuntimeError("generator didn't stop") else: if value isNone: # Need to force instantiation so we can reliably # tell if we get the same exception back value = type() try: self.gen.throw(type, value, traceback) except StopIteration as exc: # Suppress StopIteration *unless* it's the same exception that # was passed to throw(). This prevents a StopIteration # raised inside the "with" statement from being suppressed. return exc isnot value except RuntimeError as exc: # Don't re-raise the passed in exception. (issue27122) if exc is value: returnFalse # Likewise, avoid suppressing if a StopIteration exception # was passed to throw() and later wrapped into a RuntimeError # (see PEP 479). if type is StopIteration and exc.__cause__ is value: returnFalse raise except: # only re-raise if it's *not* the exception that was # passed to throw(), because __exit__() must not raise # an exception unless __exit__() itself failed. But throw() # has to raise the exception to signal propagation, so this # fixes the impedance mismatch between the throw() protocol # and the __exit__() protocol. # if sys.exc_info()[1] is value: returnFalse raise raise RuntimeError("generator didn't stop after throw()")