3

我正在使用带有 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)并登录到文件系统,而不是记录到数据库。

4

1 回答 1

2

使用transaction.commit()对其他正在提交的模型的更改也会产生意想不到的副作用,这并不是太酷 - 使用 ZopeTransactionExtension 设置“正常” Pyramid 会话背后的想法是,单个会话在请求开始时开始,然后如果一切都成功了会话被提交,如果有异常,那么一切都回滚。最好保留此逻辑并避免在请求中间手动提交内容。

(作为旁注 - DBSession.flush() 不提交事务,它发出 SQL 语句,但事务可以稍后回滚)

对于异常日志之类的东西,我会考虑设置一个单独的会话,它不绑定到 Pyramid 的请求/响应周期(没有 ZopeTransactionExtension),然后使用它来创建日志记录。添加日志记录后,您需要手动提交事务:

record = Log("blah")
log_session.add(record)
log_session.commit()
于 2013-02-14T06:44:53.333 回答