Python SQLalchemy会话在守护进程中出现问题,但在金字塔中没有。我可能会错过什么?
为了保持整洁,我想我会把这个问题变成另一个问题。其依据是: 和 所以这里的交易是:我有一个金字塔应用程序,它与一个守护进程通信,而守护进程又与一个数据库通信 现在,由于某些原因,当我将内容添加到数据库会话变量时,它没有被提交到数据库,如中所示:Python SQLalchemy会话在守护进程中出现问题,但在金字塔中没有。我可能会错过什么?,python,python-3.x,sqlalchemy,pyramid,python-3.2,Python,Python 3.x,Sqlalchemy,Pyramid,Python 3.2,为了保持整洁,我想我会把这个问题变成另一个问题。其依据是: 和 所以这里的交易是:我有一个金字塔应用程序,它与一个守护进程通信,而守护进程又与一个数据库通信 现在,由于某些原因,当我将内容添加到数据库会话变量时,它没有被提交到数据库,如中所示: DBSession.add(ModelInstance) 调用flush或commit不能使其成为commit 以下是我制作DBSession的方式: settings = { 'sqlalchemy.url':'blah bl
DBSession.add(ModelInstance)
调用flush或commit不能使其成为commit
以下是我制作DBSession的方式:
settings = {
'sqlalchemy.url':'blah blah'
}
DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
engine = engine_from_config(settings, 'sqlalchemy.')
DBSession.configure(bind=engine)
这对我来说很好,因为我可以很好地查询数据库。ie:这类事情很有效:
DBSession.query(ModelClass).get(id)
这位优秀的绅士建议使用以下代码:
import transaction
transaction.commit()
这很好地确保了我的东西得到了承诺。唯一的问题是,它以某种方式使我的DBSession变得无用。因此,如果我想使用会话跟踪的对象,我需要重新实例化会话和这些项。这太糟糕了。这要花很多时间
简言之,我的问题是,我如何避免这种情况
从长远来看:
- 如何让我的DBSession在不破坏它的情况下正确提交
- 如何在不需要长时间数据库调用的情况下修复DBSession和关联的模型实例
- 知道为什么会这样吗?我已经成功地在我提到的金字塔应用程序中以同样的方式构建了一个DBSession,它工作得非常好,它在我想要的时候就提交了,而且一切都正常
commit()
的另一个行为是,默认情况下,它会使状态过期
提交完成后存在的所有实例的。这是如此
下次访问实例时,通过属性访问或
或者,如果他们出现在查询
结果集中,他们得到的信息最多
最近的状态。要禁用此行为,请使用配置sessionmaker()
在提交时过期=False
看起来问题是故意的:提交时,所有对象都标记为过期。这样做是为了避免继续使用数据库中可能已更改的旧缓存值
它在金字塔中工作的原因是每个请求都有自己的事务,并且在处理它们之前查询对象。您尝试使用预览事务中的对象,这可能不是一个好主意,因为它们可能与数据库不同步
要解决您的问题,您可以确保在事务结束后不重用对象(可能需要您的事务包含更多内容),或者按照事务中的建议使用expire\u on\u commit=False
。但如果使用后者,请注意对象可能已过时。根据
commit()
的另一个行为是,默认情况下,它会使状态过期
提交完成后存在的所有实例的。这是如此
下次访问实例时,通过属性访问或
或者,如果他们出现在查询
结果集中,他们得到的信息最多
最近的状态。要禁用此行为,请使用配置sessionmaker()
在提交时过期=False
看起来问题是故意的:提交时,所有对象都标记为过期。这样做是为了避免继续使用数据库中可能已更改的旧缓存值
它在金字塔中工作的原因是每个请求都有自己的事务,并且在处理它们之前查询对象。您尝试使用预览事务中的对象,这可能不是一个好主意,因为它们可能与数据库不同步
要解决您的问题,您可以确保在事务结束后不重用对象(可能需要您的事务包含更多内容),或者按照事务中的建议使用
expire\u on\u commit=False
。但是如果您使用后者,请注意对象可能已经过时。在SQLAlchemy会话中,提交时将使它们管理的对象过期。这是合理的,因为在提交之后,您无法保证在并发世界中其他东西不会改变它们试图在数据库中镜像的状态
Pyramid建议使用事务管理器来帮助您维护每个请求的单个事务。请求完成后,它将自动为您调用transaction.commit()
。这样,您就不必考虑/担心对象将过期,如果代码引发异常,事务将正确中止
设置事务管理器的方法是安装pyramid_tm
和zope.sqlalchemy
,然后将DBSession
连接到zope.sqlalchemy.ZopeTransactionExtension
。然后事情就会“正常运转”
如果需要填充新对象的主键或确保某些SQL能够正确执行,则可以使用DBSession.flush()
在事务中执行SQL,而无需实际提交它。任何错误都会在那里提出,供您捕捉和处理
课程的基本设置在金字塔文档的教程中介绍:
更新:我意识到我已经回答了您关于在金字塔中使用事务管理器的问题,您已经成功地使用了它。我认为答案也清楚地解释了ZopeTransactionExtension
,但是,您只需要确认提交事务。明智的做法是在脚本中使用一个事务,您可以通过
import transaction
with transaction.manager:
# do tons of database stuff
现在,如果发生异常,事务将被中止,如果没有,事务将被提交。在SQLAlchemy会话中,obje将过期
import transaction
with transaction.manager:
# do tons of database stuff