If you have some objects (such as a file, a network connection or lock), with the need to support the statement, the following describes two methods defined.
method 1):
First introduced to the works with
(1) keeping up with the following statements is evaluated, the returned object ' __enter__()
' method is called, the return value of this method will be assigned to as the back of the variables;
(2) when the latter with after all of the code block is executed, the call returns an object in front, " __exit__()
" method.
It works with code examples:
class Sample:
def __enter__(self):
print "in __enter__"
return "Foo"
def __exit__(self, exc_type, exc_val, exc_tb):
print "in __exit__"
def get_sample():
return Sample()
with get_sample() as sample:
print "Sample: ", sample
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Operation result code as follows:
in __enter__
Sample: Foo
in __exit__
- 1
- 2
- 3
Can be seen, the entire operation process is as follows:
(. 1) Enter () method is executed;
Return value (2) enter () method in this case is the "Foo", assigned to the variable Sample;
(. 3) block of code print sample value of the variable "Foo";
(. 4) Exit () method is called;
[NOTE:] exit () method has three parameters, exc_type, exc_val, exc_tb, these parameters are very useful in the exception process.
exc_type: the type of error
exc_val: the value corresponding to the error type
exc_tb: location code error occurs in
the sample code:
class Sample():
def __enter__(self):
print('in enter')
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print "type: ", exc_type
print "val: ", exc_val
print "tb: ", exc_tb
def do_something(self):
bar = 1 / 0
return bar + 10
with Sample() as sample:
sample.do_something()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
Program output:
in enter
Traceback (most recent call last):
type: <type 'exceptions.ZeroDivisionError'>
val: integer division or modulo by zero
File "/home/user/cltdevelop/Code/TF_Practice_2017_06_06/with_test.py", line 36, in <module>
tb: <traceback object at 0x7f9e13fc6050>
sample.do_something()
File "/home/user/cltdevelop/Code/TF_Practice_2017_06_06/with_test.py", line 32, in do_something
bar = 1 / 0
ZeroDivisionError: integer division or modulo by zero
Process finished with exit code 1
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
Method (2):
The easiest way to implement a new context manager is to use contexlib module @contextmanager decorator. Here's an example of a context manager code block timing functions:
import time
from contextlib import contextmanager
@contextmanager
def timethis(label):
start = time.time()
try:
yield
finally:
end = time.time()
print('{}: {}'.format(label, end - start))
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
# Example use
with timethis('counting'):
n = 10000000
while n > 0:
n -= 1
- 1
- 2
- 3
- 4
- 5
Timethis the function (), the code as to the yield in the context manager __enter__()
method is performed, all the codes as would yield after __exit__()
performing the method. If an exception occurs, an exception will be thrown in the yield statement there.
[Note]
1, @ contextmanager should only be used to write self-contained context management function.
2, if you have some objects (such as a file, a network connection or lock), the need to support with the statement, then you need to implement a separate __enter__()
method and __exit__()
method.