python - 使用 SQLAlchemy 创建 Pyramid Session 时出现 DetachedInstanceError

标签 python sqlalchemy pyramid zope

我自己编写了 ISession 的实现interface应该将 Session 存储在数据库中的 Pyramid 。一切都很好,但不知何故 pyramid_tm吐了这个。一旦它被激活,它就会说:

DetachedInstanceError: Instance <Session at 0x38036d0> is not bound to a Session;
attribute refresh operation cannot proceed

(不要在这里混淆:<Session ...> 是模型的类名,“... to a Session”很可能指的是 SQLAlchemy 的 session (我称之为 DBSession 以避免混淆)。

我查看了邮件列表和 SO,似乎任何时候有人遇到问题,他们都是

  • 产生一个新线程或
  • 手动调用transaction.commit()

这两件事我都不做。然而,这里的特点是,我的 session 经常被 Pyramid 传递。首先我做DBSession.add(session)然后 return session .之后我可以处理 session 、闪烁新消息等。

但是,似乎一旦请求完成,我就会收到此异常。这是完整的回溯:

Traceback (most recent call last):
  File "/home/javex/data/Arbeit/libraries/python/web_projects/pyramid/lib/python2.7/site-packages/waitress-0.8.1-py2.7.egg/waitress/channel.py", line 329, in service
    task.service()
  File "/home/javex/data/Arbeit/libraries/python/web_projects/pyramid/lib/python2.7/site-packages/waitress-0.8.1-py2.7.egg/waitress/task.py", line 173, in service
    self.execute()
  File "/home/javex/data/Arbeit/libraries/python/web_projects/pyramid/lib/python2.7/site-packages/waitress-0.8.1-py2.7.egg/waitress/task.py", line 380, in execute
    app_iter = self.channel.server.application(env, start_response)
  File "/home/javex/data/Arbeit/libraries/python/web_projects/pyramid/lib/python2.7/site-packages/pyramid/router.py", line 251, in __call__
    response = self.invoke_subrequest(request, use_tweens=True)
  File "/home/javex/data/Arbeit/libraries/python/web_projects/pyramid/lib/python2.7/site-packages/pyramid/router.py", line 231, in invoke_subrequest
    request._process_response_callbacks(response)
  File "/home/javex/data/Arbeit/libraries/python/web_projects/pyramid/lib/python2.7/site-packages/pyramid/request.py", line 243, in _process_response_callbacks
    callback(self, response)
  File "/home/javex/data/Arbeit/libraries/python/web_projects/pyramid/miniblog/miniblog/models.py", line 218, in _set_cookie
    print("Setting cookie %s with value %s for session with id %s" % (self._cookie_name, self._cookie, self.id))
  File "build/bdist.linux-x86_64/egg/sqlalchemy/orm/attributes.py", line 168, in __get__
    return self.impl.get(instance_state(instance),dict_)
  File "build/bdist.linux-x86_64/egg/sqlalchemy/orm/attributes.py", line 451, in get
    value = callable_(passive)
  File "build/bdist.linux-x86_64/egg/sqlalchemy/orm/state.py", line 285, in __call__
    self.manager.deferred_scalar_loader(self, toload)
  File "build/bdist.linux-x86_64/egg/sqlalchemy/orm/mapper.py", line 1668, in _load_scalar_attributes
    (state_str(state)))
DetachedInstanceError: Instance <Session at 0x7f4a1c04e710> is not bound to a Session; attribute refresh operation cannot proceed

对于这种情况,我停用了调试工具栏。一旦我激活它,错误就会从那里抛出。看来这里的问题是随时访问对象。

我意识到我可以尝试以某种方式分离它,但这似乎不是正确的方法,因为如果不再次明确地将它添加到 session 中,就无法修改该元素。

因此,当我没有生成新线程并且我没有显式调用提交时,我猜事务在请求完全消失之前提交,之后又可以访问它。我该如何处理这个问题?

最佳答案

我相信您在这里看到的是一个奇怪的事实,即响应回调和完成的回调实际上是在补间之后执行的。它们位于您应用程序的导出和中间件之间。 pyramid_tm,作为补间,在您的响应回调执行之前提交事务 - 导致以后访问时出错。

正确排列这些东西的顺序很困难。我想到的一个可能性是在 under pyramid_tm 上注册您自己的补间,它在 session 上执行刷新,获取 ID,并在响应中设置 cookie。

我对这个问题表示同情,因为事务提交后发生的任何事情都是 Pyramid 中真正的灰色区域,并不总是很清楚 session 不应该被触及。我会记下来继续思考如何在未来改进 Pyramid 的这个工作流程。

关于python - 使用 SQLAlchemy 创建 Pyramid Session 时出现 DetachedInstanceError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15351515/

相关文章:

python - 使用工作层在 Elastic Beanstalk 上使用 Django 设置计划/cron 作业

python - subprocess.communicate - 读取未换行终止的行

javascript - Django、gevent-socketio 和 session

python - 使用 sqlalchemy 嵌套 SELECT

python - Pyramid SQLAlchemy 数据库更改在重新加载时消失

javascript - 如何将 Pyramid 的FileResponse接收到ajax中?

python - 仅当另一个 n*n 的值具有特定值时才显示 n*n 矩阵的值 (Python)

python - SQLAlchemy 声明式。指定要选择的列

Python、SQLAlchemy 在 connection.execute 中传递参数

python - 在 Pyramid 中发送分块二进制文件的 header