In this post, I will discuss the python syntax with. We can use this syntax in exception handling to make the code cleaner and much more readable. It simplifies the management of common resources like file streams.
In python, we can use try and except as follows:
1 | try: # Try to do something |
For example:
1 | try: |
We can use a shorter code to the exact same thing:
1 | with open('aFile.txt') as f: |
As we can see, with can make the code shorter.
To use with in python, there are some definitions to understand:
Context Management Protocol
Context Management Protocol contains two methods: .__enter__() and .__exit__(). The former (.__enter__() method) is to allocate resource, while the latter (.__exit__() method) is to free the resource.
An object with these two methods can be processed by with.
Context Manager
An object with methods .__enter__() and .__exit__() is called context manager. For this example, the output of open('aFile.txt') (which is an object) is the context manager.
Context Expression
The syntax after with is called context expression. This syntax should return a context manager. For this example, open('aFile.txt') is a context expression.
With-body
The syntaxes wrapped up by with syntax are called with-body. For this example, data = f.read() is the with-body.
The standard format of with syntax is as follows:
1 | with conetext_expression [as target(s)]: |
Then the process of with syntax is:
- Execute
.__enter__()method, the output of this method will be assigned to variabletarget. - Execute with-body syntaxes.
- Execute
.__exit__()method.
An example can be seen as follows:
1 | class Manager: |
If we execute the with code as follows:
1 | with Manager('Amy') as test: |
The output is as follows:
1 | [Enter Amy]: Allocate resource. |
If any exception raises, we can simulate this situation with code as follows:
1 | with Manager('Amy') as test: |
The output is as follows:
1 | [Enter Amy]: Allocate resource. |
Module contextlib provided three objects, contextmanager, function nested() and closing. I will focus on nested() here.
Function nested() can organize many Context Managers together without nested syntaxes.
See this example:
1 | with nested(A(), B(), C()) as (X, Y, Z): |
This is the same as:
1 | with A() as X: |