关于一个yield和with的问题
from flask_sqlalchemy import SQLAlchemy as BaseSQLAlchemyfrom contextlib import contextmanager
#自定义一个SQLAlchemy继承flask_sqlalchemy的,方便自定义方法!!!
class SQLAlchemy(BaseSQLAlchemy):
#利用contextmanager管理器,对try/except语句封装,使用的时候必须和with结合!!!
@contextmanager
def auto_commit_db(self):
try:
yield # <---这里这个yield怎么理解?
self.session.commit()
except Exception as e:
# 加入数据库commit提交失败,必须回滚!!!
self.session.rollback()
raise e
db = SQLAlchemy()
添加数据的时候需要用到with:
with db.auto_commit_db(): user_db = User(nickname=self.nickname, password=self.password)
db.session.add(user_db)
回答:
建议深入理解生成器后研究下contextlib的代码,下面简单解释下contextmanager怎么把被修饰对象的 try ... finally ... 分配到with约定的 __enter__
, __exit__
方法中的。
contextmanager的使用方式,可见他要求装饰对象是一个生成器
Typical usage: @contextmanager
def some_generator(<arguments>):
<setup>
try:
yield <value>
finally:
<cleanup>
此处yield的作用就是协程切换,如果yield后有值,还可以传出(with 子句 as 后)。
contextmanager 在 __enter__
中第一次调用 next(gen)
,代码执行到auto_commit_db
的yield
处转出,执行 with
子句的代码
user_db = User(nickname=self.nickname, password=self.password)db.session.add(user_db)
contextmanager 在 __exit__
中第二次调用 next(gen)
,也就就是with子句结束前执行auto_commit_db的其余部分,完成资源管理的其他任务。
回答:
等待 self.session.commit()执行返回
以上是 关于一个yield和with的问题 的全部内容, 来源链接: utcz.com/p/937677.html