python的上下文管理


  說道上下文管理首先想到的就是這個:

class MyResource:
    def __enter__(self):
        print("查詢開始")
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("查詢結束")

    def query(self):
        print("查詢中")

with MyResource() as f:
    f.query()

  執行結果

查詢開始
查詢中
查詢結束

  但是我們這里要說的不是這個,

from contextlib import contextmanager


class MyResource:
    def query(self):
        print("查詢中")

@contextmanager
def make_myresource():
    print("查詢開始")
    yield MyResource()
    print("查詢結束")

# 這里的f是yield后面返回的實例
with make_myresource() as f:
    f.query()

  python給了我們一個contextmanager,contextmanager最大的好處就是可以將不是上下文處理器的類變成一個類似上下文處理的方式來解決問題。

  上面的運行結果依然是:

查詢開始
查詢中
查詢結束

  簡單的例子,我想把我一本圖書的名字加上書名號輸出:

from contextlib import contextmanager


@contextmanager
def make_myresource():
    print("", end='')
    yield
    print("")

# 這里的f是yield后面返回的實例
with make_myresource():
    print("my world", end='')
《my world》

  下面看一個例子:

try:
    # 此時已經支持事務,commit之前都沒有真正提交
    gift = Gift()
    gift.isbn = isbn
    # current_user是實例化后的user模型
    gift.uid = current_user.id
    current_user.beans += 0.5
    db.session.add(gift)
    db.session.commit()
except Exception as e:
    db.session.rollback()
    raise e

  這個例子是sqlalchemy操作里時常要使用到的事務回滾的代碼,為了防止本次寫入失敗對下一次寫入的影響,我們時常需要捕捉到異常並回滾到初始狀態。這樣的異常捕獲代碼會多次出現在我們的項目里面,所以我們考慮修改他,如何讓代碼簡化,這時候應當使用contextmanager來解決這個問題。

from contextlib import contextmanager

from flask_sqlalchemy import SQLAlchemy as _SQLAlchemy
from sqlalchemy import Column, SmallInteger


class SQLAlchemy(_SQLAlchemy):
    @contextmanager
    def auto_commit(self):
        try:
            yield
            self.session.commit()
        except Exception as e:
            self.session.rollback()
            raise e


db = SQLAlchemy()
@web.route('/gifts/book/<isbn>')
@login_required
def save_to_gifts(isbn):
    if current_user.can_save_to_list():
        with db.auto_commit():
            # 此時已經支持事務,commit之前都沒有真正提交
            gift = Gift()
            gift.isbn = isbn
            # current_user是實例化后的user模型
            gift.uid = current_user.id
            current_user.beans += 0.5
            db.session.add(gift)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM