Python 3.7 learning notes 27 context manager

Keywords: SQL Database Python Windows

Python 3.7 learning notes 27 context manager

Input and output of files, connection and disconnection of database are common resource management operations. Because of limited resources. In such a scenario. If these resources are used but not released. It will cause resource leakage. Light makes the system slow, heavy makes the system crash.

1, Scene based

Here's the code for death. We open 100000000 files at a time. But just write it in. Instead of closing the file. It will not only report the leakage of resources in the end. If it's serious, it will crash the computer. So don't execute the following code.

# Typically not closed. Will cause resource leakage
for x in range(1000000000):
    f = open('test.txt','w')
    f.write('test')


# The general rate will be reported
OSError:[Errno 23] Too many open........

# And the cpu of your computer is going to go crazy. If it's a windows system, or worse. It's normal to crash.

 

In order to solve the above kind of possible human error. Context management mechanism is introduced in python. It helps you automatically allocate resources and free them. The most typical application is the with statement. The above code can be rewritten as follows. The with statement completes each execution. Internally, it is equivalent to f.close() closing the file. Release resources.

# Don't run this code if you have nothing to do. Otherwise, it will hurt to create so many new files and delete them. Number of number of cycles tested.
for x in range(100000000):
    with open('test.txt','w') as f:
        f.write('test')

Of course, there is another way of writing. Remember what we learned. Whether or not the front error. finally to be executed

for x in range(10000000):
    f = open('test.txt', 'w')
    try:
        f.write('hello')
    finally: # try the code block here is an exception. Closing the file is also performed
        f.close()

But compare the simplicity of the code. We still tend to use the with statement. Similar to other scenarios such as database process locks. Try it on your own.

2, Class based context management

When creating the context manager of a class, you must ensure that the class contains__ enter__ ()   __ exit__ (). Below. We also understand the internal logic of with. In fact, it encapsulates two methods. Give them all the functions of managing resources. We just care about our own operations such as write and read.

class FileManager:
    def __init__(self, name, mode):
        print('Initializing class variables')
        self.name = name
        self.mode = mode
        self.file = None

    def __enter__(self):
        """
        //Return resources to be managed
        :return:
        """
        print('Call: return the resource function to be managed')
        self.file = open(self.name, self.mode)
        return self.file

    def __exit__(self, exc_type, exc_val, exc_tb):
        """
        //Release the operation to clean up resources. When an exception is thrown. Information will be passed into these three variables
        :param exc_type:exception_type
        :param exc_val:exception_vale
        :param exc_tb:traceback
        :return:
        """
        print('Call the release resource function')
        if self.file:
            self.file.close()
        if exc_type:
            print(f'exception_type: {exc_type}') # Starting with f indicates that python expressions within braces are supported within strings
            print(f'exc_value: {exc_val}')
            print(f'exc_traceback: {exc_tb}')


with FileManager('test.txt', 'w') as f:
    print('Test write file')
    f.write('I am the written word')
    raise Exception('Active trigger exception').with_traceback(None)

In addition to file management, the following are the most common database connections

import pymysql


class MySql:
    def __init__(self, host, user, password, port, db):
        """
        //Initialization parameter value
        :param host: address
        :param user: account number
        :param password: password
        :param port: Port number
        :param db: Database name
        """
        self.host = host
        self.user = user
        self.password = password
        self.port = int(port)
        self.db = db
        self.value = True

    def __enter__(self):
        """
        //Connect to database and return instantiated object
        :return:
        """
        try:
            self.sqlConn = pymysql.connect(
                host=self.host,
                user=self.user,
                password=self.password,
                db=self.db,
                charset="utf8",
                port=self.port)
            self.sqlCursor = self.sqlConn.cursor()
        except Exception as e:
            self.value = False
            self.err = e
            return self

        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        """
        //Close database connection to release resources
        :param exc_type:
        :param exc_val:
        :param exc_tb:
        :return:
        """
        try:
            self.sqlCursor.close()
        except:
            pass

    def select(self,sql):
        """
        //Query data
        :param sql:
        :return: Normal return=[{},{},{}.....]  Exception returns error information directly
        """
        if self.value:
            try:
                self.sqlCursor.execute(sql)
                cur = self.sqlCursor.description  # Field name of the query return value
                result = self.sqlCursor.fetchall()  # Value returned by query
            except BaseException as e:
                return e

            data = []
            # Parse the query result value into the format of the expected data type
            try:
                for i in range(len(result)):
                    lie = {}
                    for j in range(len(cur)):
                        lie[cur[j][0]] = result[i][j]
                    data.append(lie)
            except BaseException as e:
                return e

            return data
        else:
            return self.err

    def update(self,sql):
        """
        //Update data
        :param sql:
        :return: 
        """

        try:
            # Execute SQL statement
            self.sqlCursor.execute(sql)
            # Commit to database execution
            self.sqlConn.commit()
        except BaseException as e:
            # Rollback on error
            self.sqlConn.rollback()
            return e

        return

    def insert(self,sql):
        """
        //New data
        :param sql:
        :return: 
        """
        try:
            self.sqlCursor.execute(sql)
            self.sqlConn.commit()
        except BaseException as e:
            self.sqlConn.rollback()
            return e

        return

 

 

Posted by mcmuney on Mon, 15 Jun 2020 19:33:05 -0700