What is context manager
In short, the purpose of the context manager is to specify the scope of use of the object. If it is out of the scope, take the corresponding "processing"; for example:
f = open('filename.txt') data = f.read() f.close()
Open a file, read the contents of the file, and close the file. In normal business, it's not enough to write like this, because there may be errors when operating resources. In order to strengthen the code robustness, it needs to be changed frequently as follows:
try: f = open('filename.txt') data = f.read() except: pass finally: f.close()
No matter what error occurs, close and release the resource f.close() finally. In order to make the code more readable and less error prone, with will be used to implement the context manager:
with open('filename.txt') as f: data = f.read()
First, clear up some concepts:
1. Context expression: with open('filename.txt') as f:2. Context manager: open('filename.txt')3. f is not a context manager, but a resource object. It is the object returned by the context manager
Implement context manager
To implement such a context management, you need to know the context management protocol first. In short, in a class, the methods of "enter" and "exit" are implemented. The instance of this class is a context manager.
class MyResource: def __enter__(self): print('opening resource......') return self def operate(self): print('doing something......') def __exit__(self, exc_type, exc_val, exc_tb): print('closing resource......') with MyResource() as r: r.operate()
When the resource is opened, enter the ﹣ enter ﹣ method, and the return object will be assigned to the as object, i.e. the return self object will be assigned to r; no matter whether there is an error or not, after executing the with code block, you will enter the ﹣ exit ﹣ method. If there is an error, the parameter of ﹣ exit ﹣ will be assigned.
Business actual combat
The implementation of a context manager connecting mysql database is based on the above code
import pymysql class MyResource: def __init__(self, database): self.database = database def __enter__(self): self.conn = pymysql.connect( host='localhost', port=3306, user='root', password='xxxxxx', database=self.database, charset='utf8' ) self.cursor = self.conn.cursor() return self.cursor def __exit__(self, exc_type, exc_val, exc_tb): self.conn.commit() self.cursor.close() self.conn.close() with MyResource('datatbase') as db: db.execute('update test set name="rhys" where id=1')
Instantiate the MyResource object with with with, enter the enter function to connect to the database, return the cursor cursor to DB, db.execute for update operation, enter the exit function when exiting the with code block, perform the commit operation, and then close the cursor and connection.
Context manager implements context manager
There is another way to implement a up and down manager, which is to use the contextmanager decorator in contextlib:
from contextlib import contextmanager import pymysql @contextmanager def mysqldb(database): try: conn = pymysql.connect( host='localhost', port=3306, user='root', password='xxxxxx', database=database, charset='utf8' ) cursor = conn.cursor() yield cursor conn.commit() except Exception as e: print(e) finally: cursor.close() conn.close() with mysqldb('database') as db: db.execute('update test set name="rhys" where id=1')
The function decorated by the contextmanager will become a context manager. Use yield to return the cursor to the db after as. When the update operation is finished, exit the with code block, return to the yield position, and execute the subsequent code.
I prefer to use content manager to implement the query manager. The code is easier to write and understand.
Pay attention to the official account: everyday bug, suitable for people who accumulate skills and learn technology by trivial time.