As a native Java programmer, it is hard to learn a new language without comparing everything to Java, and Java 7 introduces a new feature that eliminates much of the repetitive code.try-with-resources
feature, you don't have to try/finally every time to release resources (the inconvenience is that local variables must be declared before the try, and there is a nested try/catch in the finally to handle exceptions). For example, the following Java code
try(InputStream inputStream = new FileInputStream("")) { (()); } catch (Exception ex) { }
Its corresponding code without the try-with-resources syntax would be
InputStream inputStream = null; try { inputStream = new FileInputStream(""); } catch (Exception ex) { } finally { if(inputStream != null) { try { (); } catch (Exception ex) { } } }
Similarly, Python has its own way of writing try-with-resources, the with keyword, which is based on a concept called Context Manager.
The use of the with keyword
with open('some_file', 'w') as opened_file: opened_file.write('Hola!')
The above code is equivalent to
opened_file = open('some_file', 'w') try: opened_file.write('Hola!') finally: opened_file.close()
That is, resources opened by the with keyword are automatically released by calling the appropriate method at the end of the with statement block (regardless of whether there is an exception in the with operation).
with is handy to use, but what kind of resources can use the with keyword, and how does Python know which method to call to close a resource? How does Python know which method to call to close a resource, and how do you implement your own Python class that supports a context manager?
Recall again that Java'stry-with-resources
Grammar.try(...)
The classes supported by the parentheses must be classes that implement theAutoCloseable
interface, whose interface methods are
public void close() throws IOException
That is, Java'stry-with-resources
The syntax automatically calls these methods to free the resource, so to implement Java that can be freed automatically, you just have to follow this rule.
In Python, there are two implementations of classes that can be with
Classes that implement basic methods to support the context manager
A Python class should be able to be used for with
context, must implement at least__enter__
respond in singing__exit__
methods. The meaning of these two methods is well understood, one after creating the resource and the latter after exiting the with
after the statement block. See the following example
class File(object): def __init__(self, file_name, method): self.file_obj = open(file_name, method) def __enter__(self): print("---enter") return self.file_obj def __exit__(self, type, value, traceback): print("---exit") self.file_obj.close() with File('', 'r') as data_file: print(data_file.read())
Suppose the contents of the file are
hello
world
Then the output of the above program after execution is
--enter
hello
world
---exit
- The value returned by __enter__ is used as the value of the data_file variable in with ... as data_file. as data_file, and if __enter__ doesn't return a value, data_file gets a NoneType object.
- __exit__ can be utilized to release resources.
- Attempting to execute without the __enter__ method using the with syntax results in an AttributeErro: __enter__ exception.
- Similarly, attempting to execute without the __exit__ method using the with syntax will result in an AttributeErro: __exit__ exception.
- __exit__ has three additional arguments to get the value of the resource and to handle exceptions in the with block.
- The return value of __exit__ is also useful. If it returns True, then the exception is not propagated, otherwise it is thrown directly.
Methods to create support for context managers using generators and decorators
This approach is simpler, although the logical controls are not as strong.
from contextlib import contextmanager @contextmanager def open_file(name, method): f = open(name, method) yield f ()
The execution code using f will be placed in theyield f
The location of thewith
Use the above method.yield
The f variable will bewith...as
variable value after
with open_file('some_file', 'w') as file_object: file_object.write('hola!')
Here we also need to pay attention to the exception handling situation, for example, the above code to open the file mode changed to r, still trying to write the file, so in theopen_file
methodologicalyield f
position will generate an exception that will cause the ()
Does not get executed and does not release the resource correctly.
Desire to be more defensive, frontyield f
It can be extended in the following form
try: yield f except Exception as ex: pass #Handle exceptions, or continue to throw them out finally: ()
@contextmanager
The decorator is also internally encapsulated into a single implementation of the__enter__
respond in singing__exit__
method of the object.
Reference Links:Context Managers
The above is a detailed explanation of python with context manager, more information about python with context manager please pay attention to my other related articles!