天天看點

with 與上下文管理器

對于系統資源如檔案、資料庫連接配接、socket 而言,應用程式打開這些資源并執行完業務邏輯之後,必須做的一件事就是要關閉(斷開)該資源。

比如 Python 程式打開一個檔案,往檔案中寫内容,寫完之後,就要關閉該檔案,否則會出現什麼情況呢?極端情況下會出現 "Too many open files" 的錯誤,因為系統允許你打開的最大檔案數量是有限的。

同樣,對于資料庫,如果連接配接數過多而沒有及時關閉的話,就可能會出現 "Can not connect to MySQL server Too many connections",因為資料庫連接配接是一種非常昂貴的資源,不可能無限制的被建立。

來看看如何正确關閉一個檔案。

普通版:

def m1():
    f = open("output.txt", "w")
    f.write("人生苦短,我用python")
    f.close()
           

這樣寫有一個潛在的問題,如果在調用 write 的過程中,出現了異常進而導緻後續代碼無法繼續執行,close 方法無法被正常調用,是以資源就會一直被該程式占用者釋放。那麼該如何改進代碼呢?

進階版:

def m2():
    f = open("output.txt", "w")
    try:
        f.write("人生苦短,我用python")
    except IOError:
        print("oops error")
    finally:
        f.close()
           

改良版本的程式是對可能發生異常的代碼處進行 try 捕獲,使用 try/finally 語句,該語句表示如果在 try 代碼塊中程式出現了異常,後續代碼就不再執行,而直接跳轉到 except 代碼塊。而無論如何,finally 塊的代碼最終都會被執行。是以,隻要把 close 放在 finally 代碼中,檔案就一定會關閉。

進階版:

def m3():
    with open("output.txt", "r") as f:
        f.write("人生苦短,我用python")
           

對于資料庫的操作也可以結合上下文管理器:

資料庫的操作分三步:

1.連接配接資料庫

2.sql執行語句

3.關閉連接配接

from pymysql import *


class DB(object):
    def __init__(self, database_name, passward):
        # 連接配接資料庫
        self.conn = connect( host='localhost', port=3306, database= str(database_name), user='root', password=(passward),charset='utf8')

        # 擷取cursor
        self.cs1 =self.conn.cursor()
        # self.sql = sql
        # self.cs1.execute(self.sql)

    def __enter__(self):
        return self.cs1

    def __exit__(self, *args):
        self.cs1.close()
        self.conn.close()

with DB('taobao', 'mysql') as f:
        content = f.execute('select * from goods_brands')
        t = f.fetchall()
print(t)