我正在使用SQLAlchemy的Pyramid web框架,连接到MySQL后端。我已经放在一起的应用程序工作,但我试图通过一些增强的日志记录和异常处理来添加一些波兰语。使用SQLAlchemy进行金字塔异常日志记录 - 未提交的命令
我基于事事休金字塔现场基本SQLAlchemy的教程,使用像这样的会议:
DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
使用DBSession到查询的伟大工程,如果我需要添加一些东西,并提交到数据库我会做类似
DBSession.add(myobject)
DBSession.flush()
所以我得到我的新ID。
然后我想添加日志到数据库,所以我跟着this tutorial。这似乎很好。我最初遇到了一些奇怪的事情,并且我不确定SQLAlchemy是如何工作的,所以我已经将“transaction.commit()”更改为“DBSession.flush()”来强制日志提交(这已得到解决下面!)。
接下来,我想添加自定义异常处理的意图,我可以把一个友好的错误页面,为任何未明确捕获并仍然记录的东西。因此,基于this documentation我创建的错误处理程序,如下所示:
from pyramid.view import (
view_config,
forbidden_view_config,
notfound_view_config
)
from pyramid.httpexceptions import (
HTTPFound,
HTTPNotFound,
HTTPForbidden,
HTTPBadRequest,
HTTPInternalServerError
)
from models import DBSession
import transaction
import logging
log = logging.getLogger(__name__)
#region Custom HTTP Errors and Exceptions
@view_config(context=HTTPNotFound, renderer='HTTPNotFound.mako')
def notfound(request):
log.exception('404 not found: {0}'.format(str(request.url)))
request.response.status_int = 404
return {}
@view_config(context=HTTPInternalServerError, renderer='HTTPInternalServerError.mako')
def internalerror(request):
log.exception('HTTPInternalServerError: {0}'.format(str(request.url)))
request.response.status_int = 500
return {}
@view_config(context=Exception, renderer="HTTPExceptionCaught.mako")
def error_view(exc, request):
log.exception('HTTPException: {0}'.format(str(request.url)))
log.exception(exc.message)
return {}
#endregion
所以现在我的问题是,异常被捕获和我的自定义除外图如预期出现。但是异常不会记录到数据库中。看起来这是因为DBSession事务在任何异常情况下回滚。所以我将日志处理程序改回“transaction.commit”。这具有实际上将我的异常日志提交到数据库的效果,但是现在任何日志语句之后的任何DBSession操作都会抛出“未绑定到会话的实例”错误......这是有道理的,因为根据我在transaction.commit ()会话被清除。控制台日志始终显示我想要记录的内容,包括将日志信息写入数据库的SQL语句。但是,除非我使用transaction.commit(),否则它不会提交异常,但如果我这样做,那么我会在transaction.commit()!之后终止任何DBSession语句。
Sooooo ....我该如何设置,以便我可以登录到数据库,但也捕获并成功地将异常记录到数据库中?我觉得我想让日志处理程序使用某种单独的数据库会话/连接/实例/东西,以便它是自包含的,但我不清楚这可能如何工作。
或者我应该设计一些我想完全不同的东西?
编辑: 我确实结束了一个单独的,特定于日志的会话,专门用于将提交日志信息添加到数据库。这似乎工作得很好,直到我开始将Pyramid控制台脚本集成到组合中,其中我遇到了脚本中的会话和数据库提交问题,而不一定像在实际的Pyramid Web应用程序中那样工作。
事后(我正在做什么)而不是记录到数据库我使用标准日志记录和FileHandlers(特定的TimedRotatingFileHandlers)并登录到文件系统。
谢谢!这是我认为可能工作的方向。你提到没有绑定到ZopeTransactionExtension,但它是值得在日志处理程序本身创建一个新的会话,类似于 LogSession = scoped_session(sessionmaker(extension = ZopeTransactionExtension())) 但保持ZTE自回滚行为仍然可能有用?或者中兴通讯与请求周期无关? – 2013-02-14 15:53:51
我必须错过一些东西,但我不明白如果您尝试记录错误,在出现错误时如何回滚事务可能会有用。 – Sergey 2013-02-14 23:49:44