ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

解决问题: sqlalchemy.orm.exc.DetachedInstanceError ...

2021-05-07 21:54:07  阅读:269  来源: 互联网

标签:... account sqlalchemy return self DetachedInstanceError biz str id


今天在使用sqlalchemy时,出现一例sqlalchemy.orm.exc.DetachedInstanceError异常,值得简单记录一下过程

问题出现

Traceback (most recent call last):
  File "/Users/dennis/Documents/Projects/PythonProjects/TenMock/tencloud-sdk/tensdk/store/key_pair/service.py", line 166, in <module>
    service.create_account('123Sadfaf', 'test', '', 'data')
  File "/Users/dennis/Documents/Projects/PythonProjects/TenMock/tencloud-sdk/tensdk/core/decorator.py", line 28, in wrapper
    return func(*args, **kwargs)
  File "/Users/dennis/Documents/Projects/PythonProjects/TenMock/tencloud-sdk/tensdk/store/key_pair/service.py", line 58, in create_account
    return biz.id
  File "/Users/dennis/PycharmProjects/tencloud-sdk/lib/python3.7/site-packages/sqlalchemy/orm/attributes.py", line 465, in __get__
    return self.impl.get(state, dict_)
  File "/Users/dennis/PycharmProjects/tencloud-sdk/lib/python3.7/site-packages/sqlalchemy/orm/attributes.py", line 906, in get
    value = state._load_expired(state, passive)
  File "/Users/dennis/PycharmProjects/tencloud-sdk/lib/python3.7/site-packages/sqlalchemy/orm/state.py", line 667, in _load_expired
    self.manager.expired_attribute_loader(self, toload, passive)
  File "/Users/dennis/PycharmProjects/tencloud-sdk/lib/python3.7/site-packages/sqlalchemy/orm/loading.py", line 1345, in load_scalar_attributes
    "attribute refresh operation cannot proceed" % (state_str(state))
sqlalchemy.orm.exc.DetachedInstanceError: Instance <TenAccountInfo at 0x1081e0d50> is not bound to a Session; attribute refresh operation cannot proceed (Background on this error at: http://sqlalche.me/e/14/bhk3)

异常很明显指向service.py中的create_account函数,我们来看一下该函数。

@validated(CreateAccountOfKeyPairSchema)
def create_account(self, app: str, subject: str, custom: str, data: str) -> str:
    biz = TenAccountInfo()
    biz.id = self._account_info_id_generator.next()
    biz.app = app
    biz.subject = subject
    biz.custom = custom
    biz.data = data
    biz.invalid = 0
    biz.version = self._version_generator.next()

    self._account_info_dao.save(biz)
    return biz.id

粗粗一看,觉得挺正常的。做为习惯面向百度编程的我,把sqlalchemy.orm.exc.DetachedInstanceError在百度上一搜,还真有解决方案。网上方案基本是修改sessionmaker参数(expire_on_commit=False)。

Session = sessionmaker(bind=engine, expire_on_commit=False)

于是,尝试着改了一下,果然问题解决。

问题到这里结束了么?当然没有。
expire_on_commit这个参数缺省值为True,看名字就能知道个七七八八,我也不多说(怕说错误导大家)。改了缺省值,总是不得劲,直觉会影响效率。

我回过头又看了看代码错误的地方create_account,最特殊的就在最后两行:

self._account_info_dao.save(biz)
return biz.id

本意是保存了之后,再返回业务对象biz的id。

在看看save的代码:

def save(self, biz: TenAccountInfo) -> bool:
    with self._session_cls() as session:
        try:
            session.add(biz)
            session.commit()
        except IntegrityError as ex:
            print(ex.__cause__)
            session.rollback()
            return False
        else:
            return True

这里使用with语句,会自动执行session.close()。嗯,保持及时释放资源是个好习惯,不应该有错误。

所以,综合上述两段代码,可以猜想,错误是在session.close()后,return biz.id时,系统重新尝试使用session从数据库中刷新biz对象,而得到的错误。

于是,针对当前问题,可以通过保存id的方式,简单地解决。

解决此次问题的代码如下

@validated(CreateAccountOfKeyPairSchema)
def create_account(self, app: str, subject: str, custom: str, data: str) -> str:
    biz = TenAccountInfo()
    biz.id = self._account_info_id_generator.next()
    biz.app = app
    biz.subject = subject
    biz.custom = custom
    biz.data = data
    biz.invalid = 0
    biz.version = self._version_generator.next()

    ret = biz.id
    self._account_info_dao.save(biz)
    return ret

总结:碰到问题时,不能简单地吞掉错误,而是需要从根本原因入手解决。

标签:...,account,sqlalchemy,return,self,DetachedInstanceError,biz,str,id
来源: https://blog.51cto.com/u_15181029/2759902

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有