python中上下文管理器

什么是上下文管理器?

代碼的環(huán)境就是上下文,實現(xiàn)了上下文管理器協(xié)議的類產(chǎn)生的實例就是上下文管理器對象。
在類中聲名enterexit方法的就時實現(xiàn)了上下文管理器協(xié)議,也就是說,只要定義了這兩個方法,這個類的實例就是上下文管理器對象。

在數(shù)據(jù)庫中的應(yīng)用

在不適用上下文管理器對象時,我們一般按照連接數(shù)據(jù)庫,sql操作,讀取數(shù)據(jù),斷開連接這樣的順序進行編碼,可是連接數(shù)據(jù)庫和斷開連接這兩部是所有操作都必須要做的事,所以當(dāng)有大量sql時,按照這樣的邏輯些代碼會造成大量的冗余代碼。
我們先來看一下最原始的寫法:

class Database():
    def __init__(self):
        self.connected = False

    def connect(self):
        self.connected = True

    def close(self):
        self.connected = False

    def query(self):
        if self.connected:
            return "query data"
        else:
            raise ValueError("DB not connected.")

def handle_query():
    db = Database()
    db.connect()
    print("handling......", db.query())
    db.close()

上面這段代碼中,創(chuàng)建了一個數(shù)據(jù)庫類Database,里面定義了一個connected屬性,用來表示是否已經(jīng)連接上數(shù)據(jù)庫。
connect方法代表連接數(shù)據(jù)庫操作。close方法代表關(guān)閉數(shù)據(jù)庫連接。query方法代表查詢操作。
這是最容易想到,也是最基礎(chǔ)的操作邏輯。

生成器也能解決這個問題

生成器本質(zhì)上是一個方法,就像在你所寫的函數(shù)上套了一層接口。看一個簡單示例

def dbconn(fn):
    def wrapper(*args, **kwargs):
        db = Database()
        db.connect()
        ret = fn(db, *args, **kwargs)
        db.close()
        return ret
    return wrapper

@dbconn
def handle_query(db=None):
    print("handle---", db.query())

with可以更優(yōu)雅的解決這個問題

class Database():
    def __init__(self):
        self.connected = False

    def connect(self):
        self.connected = True

    def close(self):
        self.connected = False

    def query(self):
        if self.connected:
            return "query data"
        else:
            raise ValueError("DB not connected.")

    def __enter__(self):
        self.connect()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.close()

# 使用with來解決
def handle_query():
    with Database() as db:
        print("handle...", db.query())

# 調(diào)用handle_query()
handle_query()

可以明顯的看到,Database這個類中加入了enterexit方法。
這樣Database()就產(chǎn)生了一個實現(xiàn)了上下文管理器協(xié)議的對象,就可以使用with語句了。
with語句會自動處理連接和斷開。

with語句怎么就自動處理了呢?

當(dāng)然還是需要我們使用代碼來控制的。首先with Database() as db: 這句代碼中的db,就是enter方法的返回值。
而且執(zhí)行這句話的時候代碼會先執(zhí)行enter方法,這時就做了連接數(shù)據(jù)庫的操作。
然后才是執(zhí)行了print("handle...", db.query())這句代碼,表示處理查詢sql。
當(dāng)print語句(也就是查詢語句)執(zhí)行完了,會回調(diào)exit方法,在這里寫上關(guān)閉數(shù)據(jù)庫連接的代碼。
這樣我們就不用無限制的寫連接和斷開的代碼了。完美解決。

這個exit方法很安全,因為當(dāng)with語句中的函數(shù)體引發(fā)了異常時,也會調(diào)用eixt方法,這樣就會斷開數(shù)據(jù)庫的連接了。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 關(guān)于Mongodb的全面總結(jié) MongoDB的內(nèi)部構(gòu)造《MongoDB The Definitive Guide》...
    中v中閱讀 32,311評論 2 89
  • contextlib — Context Manager Utilities contextlib - 上下文管理...
    英武閱讀 2,992評論 0 52
  • 《圣經(jīng)》上說,人是赤裸著來到世界上的,沒有任何羞恥心。所以,上帝捏了亞當(dāng)和夏娃。他倆都是不穿衣服的,每天快樂的生活...
    木丁西的文閱讀 2,533評論 0 0
  • 《柏林:城市交響曲》是敘事的。城市交響曲以柏林普通一天的作息時間為線索,依次展開。五個樂章。第一樂章,清晨。第二樂...
    Manchild閱讀 946評論 0 1
  • ——安眠藥事件暴露 美霞的父母在張老師辦公室呆了很久,前面是美霞被叫了進去,后來緊接著陸英也被叫了進去。 原來陸英...
    _聽聽閱讀 267評論 0 1

友情鏈接更多精彩內(nèi)容