Python advanced syntax _with and context manager

Python advanced syntax

with and "Context Manager"

If you have the habit of reading the source code, you may see some excellent code often appearing with the "with" keyword statement, what scenario is it usually used in? this

forFor system resources such as files, database connections, and sockets, after the application opens these resources and executes the business logic, one thing that must be done is to close (disconnect) the resources.

For example, a Python program opens a file, writes content to the file, and then closes the file after finishing writing. Otherwise, what will happen? In extreme cases, the error "Too many open files" will appear, because the maximum number of files that the system allows you to open is limited.

Similarly, for the database, if there are too many connections and they are not closed in time, "Can not connect to MySQL server Too many connections" may appear, because database connections are a very expensive resource and cannot be created unlimited .

Let's see how to close a file properly.

regular version

def m1():
    f = open("output.txt", "w")
    f.write("python之禅")
    f.close()

There is a potential problem with this writing. If an exception occurs during the call to write, the subsequent code cannot continue to execute, and the close method cannot be called normally, so the resource will always be released by the program occupant. So how can we improve the code?

Advanced version

def m2():
    f = open("output.txt", "w")
    try:
        f.write("python之禅")
    except IOError:
        print("oops error")
    finally:
        f.close()

The improved version of the program is to try to capture the code where an exception may occur, using the try/finally statement, which means that if an exception occurs in the program in the try code block, the subsequent code will no longer be executed, and it will jump directly to the except code. Piece. In any case, the code of the finally block will eventually be executed. Therefore, as long as you put close in the finally code, the file will be closed.

Premium version

def m3():
    with open("output.txt", "r") as f:
        f.write("Python之禅")

A more concise and elegant way is to use the with keyword. The return value of the open method is assigned to the variable f. When leaving the with code block, the system will automatically call the f.close() method. The effect of with is the same as using try/finally statements. So what is its realization principle? Before talking about the principle of with, there is another concept involved, that is, the context manager (Context Manager).

What is context

Context means different meanings in different places, and it needs to be understood perceptually. In fact, context is blunt, and it has the same meaning as the context of the article. In a more popular way, I think it is better to call the environment.

Lin Chong yelled "Ah!"...

Question: What kind of heart does Lin Chong's "Ah Yeah" express?

Answer: Ah, your mother is tall!

Look, an article, I'll give you an excerpt. You can't understand it because there is context, that is, the language environment exists. What a paragraph says must be inferred from the context (the context of the article).

The app clicks a button to enter a new interface, and also save the information on which screen you skipped to, so that you can jump back correctly when you click back. If you don't save it, you won't be able to jump back correctly.

Looking at these are typical examples of context, you can understand it as an environment, (and although the context is called context, but the program generally only has the above, it is just called context. Process interruption has some problems in the operating system Next, but don’t delve into it if you don’t do this advanced question...)

Context manager

  • Any object that implements the __\enter__() and __exit__() methods can be called a context manager, and context manager objects can use the with keyword. Obviously, the file object also implements the context manager.

So how does the file object implement these two methods? We can simulate and implement our own file class, and let this class implement the __enter__() and __exit__() methods.

class File():

    def __init__(self, filename, mode):
        self.filename = filename
        self.mode = mode

    def __enter__(self):
        print("entering")
        self.f = open(self.filename, self.mode)
        return self.f

    def __exit__(self, *args):
        print("will exit")
        self.f.close()

The __enter__() method returns the resource object, here is the file object you are about to open, and the __exit__() method handles some cleanup work.

Because the File class implements the context manager, you can now use the with statement.

with File('out.txt', 'w') as f:
    print("writing")
    f.write('hello, python')

In this way, there is no need to explicitly call the close method, and the system will automatically call it, even if an exception is encountered in the middle, the close method will be called.

Another way to implement a context manager

Python also provides a contextmanager decorator, which further simplifies the implementation of the context manager. The function is divided into two parts by yield, the statement before yield is executed in the enter method, and the statement after yield is executed in the exit method. The value immediately after yield is the return value of the function.

from contextlib import contextmanager

@contextmanager
def my_open(path, mode):
    f = open(path, mode)
    yield f
    f.close()

调用
with my_open('out.txt', 'w') as f:
    f.write("hello , the simplest context manager")

to sum up

Python providesThe with syntax is used to simplify the subsequent cleanup operations of resource operations. It is an alternative to try/finally. The implementation principle is based on the context manager.
In addition, Python also provides a contextmanager decorator to further simplify the implementation of upper and lower managers.

Guess you like

Origin blog.csdn.net/weixin_42250835/article/details/89979408