zoukankan      html  css  js  c++  java
  • 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)
  • 相关阅读:
    mysql的root用户无法建库的问题
    jmeter连库获取sql结果存为参数给下一接口用
    webservice接口问题
    今日杂记-20190623
    接口测试
    pyenv和virtualenv管理python的版本(多个版本同时用)
    安装禅道
    经典题,类中的变量
    CSS简介
    python单元测试unittest
  • 原文地址:https://www.cnblogs.com/Jeffding/p/8759430.html
Copyright © 2011-2022 走看看