The with statement is used to wrap the execution of a block with methods defined by a context manager (see section With Statement Context Managers). This allows common try...except...finally usage patterns to be encapsulated for convenient reuse.
with_stmt ::= "with" with_item ("," with_item)* ":" suite
with_item ::= expression ["as" target]
The execution of the with statement with one “item” proceeds as follows:
The context expression (the expression given in the with_item) is evaluated to obtain a context manager.
The context manager's __exit__() is loaded for later use.
The context manager's __enter__() method is invoked.
If a target was included in the with statement, the return value from __enter__() is assigned to it.
Note
The with statement guarantees that if the __enter__() method returns without an error, then __exit__() will always be called. Thus, if an error occurs during the assignment to the target list, it will be treated the same as an error occurring within the suite would be. See step 6 below.
The suite is executed.
The context manager's __exit__() method is invoked. If an exception caused the suite to be exited, its type, value, and traceback are passed as arguments to __exit__(). Otherwise, three None arguments are supplied.
If the suite was exited due to an exception, and the return value from the __exit__() method was false, the exception is reraised. If the return value was true, the exception is suppressed, and execution continues with the statement following the with statement.
If the suite was exited for any reason other than an exception, the return value from __exit__() is ignored, and execution proceeds at the normal location for the kind of exit that was taken.
如果是异常退出,那么会返回false,(根据文档中的exit的描述“that __exit__() methods should not reraise the passed-in exception; this is the caller's responsibility.”,大概意思就是exit()不会处理异常,会重新抛出异常抛出给外面,由调用者处理,因为这是调用者的责任)
import time
class myContextDemo(object):
def __init__(self,gen):
self.gen = gen
def __enter__(self):
print("enter in ")
return self.gen
def __exit__(self, exc_type, exc_val, exc_tb):
#exc_type是exception_type exc_val是exception_value exc_tb是exception_trackback
print("exit in ")
if exc_type is None:#如果是None 则继续执行
print("None:",exc_type, exc_val, exc_tb)
else: #异常不为空时执行,这一步,如果with语句体中发生异常,那么也会执行
print("exception:", exc_type, exc_val, exc_tb)
print("all done")
if __name__=="__main__":
gen=(i for i in range(5,10))
G=myContextDemo(gen)
with G as f :
print("hello")
for i in f:
print(i,end="\t")
#测试1:执行体中发生异常
raise Exception("母鸡啊")
print("main continue")
结果显示:
1.抛出异常后,后面main continue不再执行
2.__exit__()中的else会执行
测试2:当else中强制返回为True时:
import time
class myContextDemo(object):
def __init__(self,gen):
self.gen = gen
def __enter__(self):
print("enter in ")
return self.gen
def __exit__(self, exc_type, exc_val, exc_tb):
#exc_type是exception_type exc_val是exception_value exc_tb是exception_trackback
print("exit in ")
if exc_type is None:#如果是None 则继续执行
print("None:",exc_type, exc_val, exc_tb)
else: #异常不为空时执行,这一步,如果with语句体中发生异常,那么也会执行
print("exception:", exc_type, exc_val, exc_tb)
print("all done")
return True #这里如果返回true可以看到发生异常后,main continue可以执行
#即,如果exc_type是true,那么会继续执行,实际上,也可以在这里处理一下异常再返回true
if __name__=="__main__":
gen=(i for i in range(5,10))
G=myContextDemo(gen)
with G as f :
print("hello")
for i in f:
print(i,end="\t")
raise Exception("母鸡啊")
# print("continue")#这里不会执行
print("main continue")
The with statement is used to wrap the execution of a block with methods defined by a context manager (see section With Statement Context Managers). This allows common try...except...finally usage patterns to be encapsulated for convenient reuse.
with_stmt ::= "with" with_item ("," with_item)* ":" suite
with_item ::= expression ["as" target]
The execution of the with statement with one “item” proceeds as follows:
The context expression (the expression given in the with_item) is evaluated to obtain a context manager.
The context manager's __exit__() is loaded for later use.
The context manager's __enter__() method is invoked.
If a target was included in the with statement, the return value from __enter__() is assigned to it.
Note
The with statement guarantees that if the __enter__() method returns without an error, then __exit__() will always be called. Thus, if an error occurs during the assignment to the target list, it will be treated the same as an error occurring within the suite would be. See step 6 below.
The suite is executed.
The context manager's __exit__() method is invoked. If an exception caused the suite to be exited, its type, value, and traceback are passed as arguments to __exit__(). Otherwise, three None arguments are supplied.
If the suite was exited due to an exception, and the return value from the __exit__() method was false, the exception is reraised. If the return value was true, the exception is suppressed, and execution continues with the statement following the with statement.
If the suite was exited for any reason other than an exception, the return value from __exit__() is ignored, and execution proceeds at the normal location for the kind of exit that was taken.
如果是异常退出,那么会返回false,(根据文档中的exit的描述“that __exit__() methods should not reraise the passed-in exception; this is the caller's responsibility.”,大概意思就是exit()不会处理异常,会重新抛出异常抛出给外面,由调用者处理,因为这是调用者的责任)
import time
class myContextDemo(object):
def __init__(self,gen):
self.gen = gen
def __enter__(self):
print("enter in ")
return self.gen
def __exit__(self, exc_type, exc_val, exc_tb):
#exc_type是exception_type exc_val是exception_value exc_tb是exception_trackback
print("exit in ")
if exc_type is None:#如果是None 则继续执行
print("None:",exc_type, exc_val, exc_tb)
else: #异常不为空时执行,这一步,如果with语句体中发生异常,那么也会执行
print("exception:", exc_type, exc_val, exc_tb)
print("all done")
if __name__=="__main__":
gen=(i for i in range(5,10))
G=myContextDemo(gen)
with G as f :
print("hello")
for i in f:
print(i,end="\t")
#测试1:执行体中发生异常
raise Exception("母鸡啊")
print("main continue")
结果显示:
1.抛出异常后,后面main continue不再执行
2.__exit__()中的else会执行
测试2:当else中强制返回为True时:
import time
class myContextDemo(object):
def __init__(self,gen):
self.gen = gen
def __enter__(self):
print("enter in ")
return self.gen
def __exit__(self, exc_type, exc_val, exc_tb):
#exc_type是exception_type exc_val是exception_value exc_tb是exception_trackback
print("exit in ")
if exc_type is None:#如果是None 则继续执行
print("None:",exc_type, exc_val, exc_tb)
else: #异常不为空时执行,这一步,如果with语句体中发生异常,那么也会执行
print("exception:", exc_type, exc_val, exc_tb)
print("all done")
return True #这里如果返回true可以看到发生异常后,main continue可以执行
#即,如果exc_type是true,那么会继续执行,实际上,也可以在这里处理一下异常再返回true
if __name__=="__main__":
gen=(i for i in range(5,10))
G=myContextDemo(gen)
with G as f :
print("hello")
for i in f:
print(i,end="\t")
raise Exception("母鸡啊")
# print("continue")#这里不会执行
print("main continue")