often see the WITH statement in Python code, carefully analyzed, you will find that the WITH statement is strong, can automatically close the resources. This is called context Manager in Python. So how do we use it, and when to use it. Here we'll have a chat. The role of the context manager
In many cases, when we have finished using a resource, we need to manually close it, such as manipulating files, establishing database connections, and so on. However, in the process of using resources, if you encounter an exception, it is likely that the error will be thrown directly, causing the resource to be closed too late. So in most programming languages, we use the "try-finally" statement to ensure that resources are closed. For example, the following Python write file code:
| 12345 |
try: f = open(' test.txt ', ' A + ') F. Write(' foo\n ') finally: F. Close() |
This is not a problem, but when the "try-finally" in the middle of the logic complex, but also with a variety of nesting, the code is not easy to maintain. Python's with statement, which can be said to be almost the same function as above "try-finally", but the code looks much more concise, we have to achieve the same function:
| 12 |
with open(' test.txt ', ' A + ') as F: f. Write(' foo\n ') |
The WITH statement follows the open () method, and if it has a return value, it can be assigned to F using the AS statement. When the WITH statement block exits, the "f.close ()" method is called automatically, ensuring that the close () method is called even if "f.write ()" has an exception.
Custom classes to use the context Manager
The "Open ()" method in the example above is Python-brought, so how do we define our own types to use with statements? In fact, you can use the context manager of Python as long as your class defines the "__enter__ ()" and "__exit__ ()" methods. The "__enter__ ()" method is called when the With statement enters, its return value is assigned to the variable after the AS keyword, and the "__exit__ ()" method is called automatically after the With statement block exits.
Let's implement a file-writing function that follows the previous section:
| 12345678910111213 |
class Openfiledemo(object): def __init__(self, filename): Self . FileName = filename def __enter__(self): Self . F = open(self. FileName, ' A + ') return self . F def __exit__(self, exc_type, exc_val, exc_ TB): Self . F. Close() with openfiledemo(' test.txt ') as F: F. Write(' foo\n ') |
Exception handling
A friend must have noticed that the "__exit__ ()" Above has three parameters, yes, they are used for exception handling. In most cases, we want the exception encountered in the WITH statement to be thrown at the end, but there are times when we want to handle these exceptions. The three parameters in the "__exit__ ()" Method Exc_type, Exc_val, EXC_TB represent the exception type, outliers, and Traceback of the exception respectively. When you have finished handling the exception, you can let the "__exit__ ()" Method return True, at which point the exception will not be thrown again. For example, we will change the "__exit__ ()" method in the example above:
| 12345 |
def __exit__(self, exc_type, exc_val, exc_tb ):Self . F. Close() if exc_type! = syntaxerror: return True return False # Raise exception when SyntaxError |
Now, if you encounter SyntaxError, the exception will be thrown normally, and other exceptions will be ignored.
Contextlib Module
There is also a contextlib module in Python that provides some simple context manager functionality.
CLOSING () method
If the WITH statement block automatically calls the "__exit__ ()" method when exiting, the WITH statement block that uses "contextlib.closing ()" will automatically invoke the close () method when exiting. Take a look at the example:
| 1234567891011 |
import contextlib class Resource(object): def Open(self): print ' Open Resource ' def close(self): print ' Close Resource ' with contextlib. Closing(Resource()) as R: R. Open() |
After the program runs, it prints out
Open Resourceclose Resource
Indicates that the object created by the resource class is assigned the variable r after the AS keyword, and the "R.close ()" method is called automatically when the With statement block exits.
ContextManager Decorator
"@contextlib. ContextManager" is an adorner, and the method it modifies is composed of two parts, separated by the yield keyword. The context manager created by this method executes the statement above yield before the code block executes, and then executes the statement below yield after the code block executes. It's easy to see an example:
| 12345678910111213 |
import contextlib import time@contextlib. ContextManager def Timeit(): start = time . Time() yield End = time . Time() usedtime = (end - start) * print ' Use time %d ms ' % usedtime /c16> with Timeit(): Time . Sleep(1) |
This "Timeit ()" method implements a timer that calculates the execution time of the WITH statement block generated by him. As can be seen, the statement above yield is like the "__enter__ ()" method described between, and yield the following statement is like the "__exit__ ()" method. The yield section is the code in the With statement block. If the yield is followed by a parameter, we can use the AS keyword to assign a value to the following variable, such as the previous example:
| 123456789 |
@contextlib. ContextManager def Timeit(): start = time . Time() yield start #... with Timeit() as starttime: print starttime #... |
It is important to note that "@contextlib. ContextManager" is not the same as the "__exit__ ()" method described earlier, and an exception is also executed. That is, the code behind yield will not be executed if the WITH statement block throws an exception. So, if necessary, you need to use "try-finally" for the yield statement.
A talk about the context manager for Python