金字塔框架(Python):覆盖默认错误视图

5
任务:当我的一个视图出现错误时,我需要显示一个自定义的错误视图。错误类型并不重要。
我尝试通过为所有异常注册一个视图来覆盖所有异常,像这样:
<view
    context="Exception"
    renderer="server_error.pt"
    />

它运行得很,所有的异常都显示在我的视图中。但问题是这些错误信息已经停止了记录。当然我可以在我的错误视图中做一些类似logger.error(traceback)的事情,但这是个愚蠢的想法。

我该如何注册一个视图来处理所有的错误而不破坏日志金字塔系统?


你必须自己记录错误或重新引发错误。如果你重新引发错误,它会被记录但不会呈现你的视图。如果你在你的视图中记录错误,它将被记录并呈现你的视图。 - Loïc Faure-Lacroix
3个回答

3

您可以通过普通的 Python 日志记录在视图中记录错误,或将响应状态设置为 500(假设您的视图现在返回成功响应的状态码为 200)。

编辑:工作示例

我不是一个日志记录专家,但我认为您在 development.ini/production.ini 中的日志记录配置会被识别,下面的示例似乎证明了这一点,但您可以自行判断.....

从默认配置更改的内容

[formatter_generic]
# format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
format = y u no work??!!?? %(message)s
# End logging configuration

视图

from pyramid.view import view_config
from webob import Response
import logging
log = logging.getLogger(__name__)

@view_config(route_name='home', renderer='templates/mytemplate.pt')
def my_view(request):
    raise ValueError("oops")
    return {'project':'tstLogError'}


@view_config(context=Exception)
def exception_view(context, request):
    log.error("The error was: %s" % context, exc_info=(context))
    return Response(status_int=500, body=str(context))

    from pyramid.view import view_config
    from webob import Response

控制台输出:

serving on http://0.0.0.0:6543
y u no work??!!?? The error was: oops
Traceback (most recent call last):
  File "/home/twillis/projects/TestLogError/local/lib/python2.7/site-packages/pyramid/tweens.py", line 20, in excview_tween
    response = handler(request)
  File "/home/twillis/projects/TestLogError/local/lib/python2.7/site-packages/pyramid/router.py", line 164, in handle_request
    response = view_callable(context, request)
  File "/home/twillis/projects/TestLogError/local/lib/python2.7/site-packages/pyramid/config/views.py", line 333, in rendered_view
    result = view(context, request)
  File "/home/twillis/projects/TestLogError/local/lib/python2.7/site-packages/pyramid/config/views.py", line 471, in _requestonly_view
    response = view(request)
  File "/home/twillis/projects/TestLogError/tstLogError/tstlogerror/views.py", line 8, in my_view
    raise ValueError("oops")
ValueError: oops

browser screenshot


就像我所说的:使用基本记录器进行日志记录是不好的解决方案。如果我这样做,就无法使用金字塔的配置对其进行记录。我尝试了状态代码设置,但它并没有改变记录情况(仍然没有错误)。 - Taras Voinarovskyi
所以你的意思是当你用浏览器访问那个视图时,浏览器看到了HTTP_STATUS=500,但它没有被记录下来?这很令人惊讶。我必须亲眼看到才能相信。 - Tom Willis
斗!在你的例子中,你自己记录了它:)。它显示为“y u no work??!!??”是因为你更改了格式化程序配置,该配置应用于所有输出到sys.error。但还是谢谢!现在我明白了,除了自己记录日志外,没有其他方法,并且格式化程序被应用,所以这似乎不是问题。 - Taras Voinarovskyi
我理解你的问题是这样的,不是吗? - Tom Willis

2

记录异常在自己的错误视图中不是愚蠢的做法(异常将作为request.context可用)。与所有异常一样,你可以什么都不做、处理异常并记录它,或者重新引发相同的异常。

在我的设置中,未捕获的异常由WSGI服务器本身记录,在这种情况下是wsgiref。无法触发WSGI服务器的正常响应机制和异常记录器。

wsgiref的异常记录器:

def log_exception(self,exc_info):
    """Log the 'exc_info' tuple in the server log

    Subclasses may override to retarget the output or change its format.
    """
    try:
        from traceback import print_exception
        stderr = self.get_stderr()
        print_exception(
            exc_info[0], exc_info[1], exc_info[2],
            self.traceback_limit, stderr
        )
        stderr.flush()
    finally:
        exc_info = None

您可以考虑的一种替代方案是在 Web 服务器层而非 Pyramid 层显示您的自定义错误页面。

谢谢你的回答。看起来我只需要在视图中记录它。 - Taras Voinarovskyi

0

插件 pyramid_exclog 很好地实现了这个目的。

它作为 tween 实现,因此您仍然可以编写 Exception 视图,并将异常详细信息记录到您在 pyramid 配置文件中指定的任何日志处理程序中 - 无论是控制台、文件还是电子邮件。

除了 pyramid_exclog 文档之外,我还发现 Python 文档中的 Configuration file format 部分非常有帮助,因为配置可能相当棘手。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接