sqlalchemy的update手动commit之前通过yield执行远程异步调用时session对象被替换

SQLAlchemy==1.2.18

result = db.session.query(ObjectModel).get(ids.get("id"))
result.status = 2   #此时 session._is_clean()  =  False

#中间执行一次yield远程调用
#外部请求函数
def onAyncFetch():
    req = ...省略其它代码
    response = yield async_http.fetch(req)
    ...省略其它代码
    return Return(json_decode(response.body))
print id(result.query.session) 
data = yield onAyncFetch(...)
print id(result.query.session) #两次打印内存地址不相同
...省略其它代码
#执行yield调用结束之后 session._is_clean()  =  True

db.session.commit() #再进行commit的会进行如下代码段,上面修改的status字段无法被commit

上面是一段伪代码.流程大概就这样,下面贴sqlalchemy时commiit的源码

sqlalchemy/orm/session.py


    def _prepare_impl(self):
        self._assert_active()
        if self._parent is None or self.nested:
            self.session.dispatch.before_commit(self.session)

        stx = self.session.transaction
        if stx is not self:
            for subtransaction in stx._iterate_self_and_parents(upto=self):
                subtransaction.commit()

        if not self.session._flushing:
            for _flush_guard in range(100):
                if self.session._is_clean():  # 判断对象信息是否变更,如果变更则执行flush()
                    break
                self.session.flush()
            else:
                raise exc.FlushError(
                    "Over 100 subsequent flushes have occurred within "
                    "session.commit() - is an after_flush() hook "
                    "creating new objects?"
                )

        if self._parent is None and self.session.twophase:
            try:
                for t in set(self._connections.values()):
                    t[1].prepare()
            except:
                with util.safe_reraise():
                    self.rollback()

        self._state = PREPARED

你可能感兴趣的:(python)