har*_*dsv 44 python sqlalchemy
我刚开始使用SQLAlchemy并获得DetachedInstanceError,并且无法在任何地方找到相关信息.我在会话之外使用实例,所以SQLAlchemy很自然无法加载任何关系,如果它们尚未加载,但是,我访问的属性不是关系,实际上这个对象根本没有任何关系.我找到了诸如渴望加载的解决方案,但我无法应用于此,因为这不是一种关系.我甚至在关闭会话之前尝试"触摸"此属性,但它仍然无法阻止异常.即使在非关系属性之前成功访问过一次之后,可能导致此异常的原因是什么?任何有关调试此问题的帮助表示赞赏.我将同时尝试获得可重现的独立场景并在此更新.
更新:这是具有几个堆栈的实际异常消息:
File "/home/hari/bin/lib/python2.6/site-packages/SQLAlchemy-0.6.1-py2.6.egg/sqlalchemy/orm/attributes.py", line 159, in __get__
return self.impl.get(instance_state(instance), instance_dict(instance))
File "/home/hari/bin/lib/python2.6/site-packages/SQLAlchemy-0.6.1-py2.6.egg/sqlalchemy/orm/attributes.py", line 377, in get
value = callable_(passive=passive)
File "/home/hari/bin/lib/python2.6/site-packages/SQLAlchemy-0.6.1-py2.6.egg/sqlalchemy/orm/state.py", line 280, in __call__
self.manager.deferred_scalar_loader(self, toload)
File "/home/hari/bin/lib/python2.6/site-packages/SQLAlchemy-0.6.1-py2.6.egg/sqlalchemy/orm/mapper.py", line 2323, in _load_scalar_attributes
(state_str(state)))
DetachedInstanceError: Instance <ReportingJob at 0xa41cd8c> is not bound to a Session; attribute refresh operation cannot proceed
Run Code Online (Sandbox Code Playgroud)
部分模型如下所示:
metadata = MetaData()
ModelBase = declarative_base(metadata=metadata)
class ReportingJob(ModelBase):
__tablename__ = 'reporting_job'
job_id = Column(BigInteger, Sequence('job_id_sequence'), primary_key=True)
client_id = Column(BigInteger, nullable=True)
Run Code Online (Sandbox Code Playgroud)
并且字段client_id是导致此异常的原因,其用法如下所示:
查询:
jobs = session \
.query(ReportingJob) \
.filter(ReportingJob.job_id == job_id) \
.all()
if jobs:
# FIXME(Hari): Workaround for the attribute getting lazy-loaded.
jobs[0].client_id
return jobs[0]
Run Code Online (Sandbox Code Playgroud)
这是稍后在会话范围之外触发异常的原因:
msg = msg + ", client_id: %s" % job.client_id
Run Code Online (Sandbox Code Playgroud)
har*_*dsv 60
我在尝试缩小导致异常的代码时找到了根本原因.我在会话结束后在不同的地方放置了相同的属性访问代码,发现在查询会话结束后它肯定不会立即引起任何问题.事实证明,在关闭为更新对象而打开的新会话后,问题开始出现.一旦我理解了在会话结束后对象的状态不可用,我就能找到讨论同一问题的这个线程.这个问题的两个解决方案是:
expire_on_commit=False到sessionmaker().第三个选项是在创建会话后手动设置expire_on_commit为False会话,如:session.expire_on_commit = False.我证实这解决了我的问题.
gly*_*bet 10
我们得到了类似的错误,即使expire_on_commit设置为False.最后,它实际上是由于两个sessionmakers都被用来在不同的请求中进行会话.我真的不明白发生了什么,但如果你看到这个例外expire_on_commit=False,请确保你没有sessionmaker初始化.