我正在使用带有 SQLAlchemy 的 Pyramid Web 框架,连接到 MySQL 后端。我组装的应用程序可以运行,但我试图通过一些增强的日志记录和异常处理来添加一些润色。
我基于 Pyramid 网站上的基本 SQLAlchemy 教程,使用如下会话:
DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
使用 DBSession 查询效果很好,如果我需要向数据库添加和提交某些内容,我会执行类似的操作
DBSession.add(myobject)
DBSession.flush()
所以我得到了我的新身份证。
然后我想将日志记录添加到数据库中,所以我按照本教程进行操作。这似乎工作得很好。我最初确实遇到了一些奇怪的事情,我不确定 SQLAlchemy 是如何工作的,所以我将“transaction.commit()”更改为“DBSession.flush()”以强制提交日志(已解决以下!)。
接下来,我想添加自定义异常处理,目的是我可以为任何没有明确捕获并仍然记录的内容放置一个友好的错误页面。因此,基于此文档,我创建了如下错误处理程序:
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(),否则它不会提交异常,
Sooooo ....我该如何设置以便我可以登录到数据库,同时也可以捕获并成功地将异常记录到数据库中?我觉得我希望日志处理程序使用某种单独的数据库会话/连接/实例/某些东西,以便它是独立的,但我不清楚它是如何工作的。
或者我应该构建我想做的完全不同的事情?
编辑:我最终使用了一个单独的、特定于日志的会话,专门用于向数据库添加提交日志信息。这似乎运作良好,直到我开始将 Pyramid 控制台脚本集成到混合中,其中我遇到了脚本中的会话和数据库提交问题,不一定像在实际 Pyramid Web 应用程序中那样工作。
事后看来(以及我现在正在做的事情),我使用标准的日志记录和 FileHandlers(特别是 TimedRotatingFileHandlers)并登录到文件系统,而不是记录到数据库。