繁体   English   中英

如何使用 CherryPy 捕获所有异常?

[英]How to catch all exceptions with CherryPy?

我使用CherryPy运行一个非常简单的 Web 服务器。 它旨在处理GET参数,如果它们正确,则对它们进行处理。

import cherrypy

class MainServer(object):
    def index(self, **params):
        # do things with correct parameters
        if 'a' in params:
            print params['a']

    index.exposed = True

cherrypy.quickstart(MainServer())

例如,

http://127.0.0.1:8080/abcde:

 404 Not Found

The path '/abcde' was not found.

Traceback (most recent call last):
  File "C:\Python27\lib\site-packages\cherrypy\_cprequest.py", line 656, in respond
    response.body = self.handler()
  File "C:\Python27\lib\site-packages\cherrypy\lib\encoding.py", line 188, in __call__
    self.body = self.oldhandler(*args, **kwargs)
  File "C:\Python27\lib\site-packages\cherrypy\_cperror.py", line 386, in __call__
    raise self
NotFound: (404, "The path '/abcde' was not found.")
Powered by CherryPy 3.2.4

我试图捕捉这个异常并显示一个空白页面,因为客户不关心它。 具体来说,无论导致异常的 url 或查询字符串是什么,结果都将是一个空体。

我查看了有关错误处理cherrypy._cperror文档,但我没有找到实际使用它的方法。

编辑:我放弃了使用CherryPy并使用BaseHTTPServer找到了一个简单的解决方案(请参阅下面我的答案,因为它解决了问题但没有回答问题...叹气...)

CherryPy的赶上你的异常。 这就是它如何通过捕获的异常将有效页面返回给浏览器。

我建议你仔细阅读所有文档。 我意识到这不是最好的文档或组织良好,但如果你至少浏览它,框架将更有意义。 它是一个小型框架,但几乎可以满足您对应用程序服务器的所有需求。

import cherrypy


def show_blank_page_on_error():
    """Instead of showing something useful to developers but
    disturbing to clients we will show a blank page.

    """
    cherrypy.response.status = 500

    cherrypy.response.body = ''


class Root():
    """Root of the application"""

    _cp_config = {'request.error_response': show_blank_page_on_error}

    @cherrypy.expose
    def index(self):
        """Root url handler"""

        raise Exception 

看到用于进一步参考上面提到的页上的文档中的示例。

选择最适合您的方法默认方法自定义错误处理

我认为你不应该使用BaseHTTPServer 如果您的应用程序非常简单,只需获得一个轻量级框架(例如Flask),即使它可能有点过分,或者保持低级别但仍然在WSGI标准内并使用符合WSGI的服务器。

您可以简单地使用try/except子句:

try:
    cherrypy.quickstart(MainServer())
except: #catches all errors, including basic python errors
    print("Error!")

这将捕获每个错误。 但是如果你只想抓住cherrypy._cperror

from cherrypy import _cperror

try:
    cherrypy.quickstart(MainServer())
except _cperror.CherryPyException: #catches only CherryPy errors.
    print("CherryPy error!")

希望这可以帮助!

Docs似乎错过了这一部分。 这是我在从源代码中查找自定义错误处理的详细说明时发现的。

自定义错误处理

预期的HTTP响应

'error_page'配置命名空间可用于为预期的响应提供自定义HTML输出(如404 Not Found)。 提供将从中读取输出的文件名。 使用普通的旧Python 字符串格式化 ,内容将使用值%(状态)s,%(消息)s,%(追溯)和%(版本)s进行插值。

_cp_config = {
    'error_page.404': os.path.join(localDir, "static/index.html")
}

从3.1版开始,您还可以提供函数或其他可调用项作为error_page条目。 它将被传递到内插到模板中的相同状态,消息,回溯和版本参数

def error_page_402(status, message, traceback, version):
    return "Error %s - Well, I'm very sorry but you haven't paid!" % status
cherrypy.config.update({'error_page.402': error_page_402})

同样在3.1中,除了编号的错误代码外,您还可以提供error_page.default来处理没有自己的error_page条目的所有代码。

意料之外的错误

CherryPy还有一个通用的错误处理机制:每当代码中出现意外错误时,它都会调用Request.error_response来设置响应状态,标题和正文。 默认情况下,这与HTTPError(500)输出相同。 如果要提供其他一些行为,通常会替换“request.error_response”。

下面是一些示例代码,演示如何显示自定义错误消息并发送包含错误的电子邮件

from cherrypy import _cperror

def handle_error():
    cherrypy.response.status = 500
    cherrypy.response.body = [
        "<html><body>Sorry, an error occurred</body></html>"
    ]
    sendMail('error@domain.com',
             'Error in your web app',
             _cperror.format_exc())

@cherrypy.config(**{'request.error_response': handle_error})
class Root:
    pass

请注意,您必须显式设置response.body而不是简单地返回错误消息。

虽然这是我搜索樱桃异常处理时的最佳结果之一,但是接受的答案没有完全回答这个问题。 以下是针对cherrypy 14.0.0的工作代码

# Implement handler method
def exception_handler(status, message, traceback, version)
    # Your logic goes here 

class MyClass()    

   # Update configurations
   _cp_config = {"error_page.default": exception_handler}

请注意方法签名。 如果没有此签名,则不会调用您的方法。以下是方法参数的内容,

  • status :HTTP状态和描述
  • message :附加到异常的消息
  • traceback :格式化堆栈跟踪
  • 版本 :Cherrypy版本

也许你可以使用cherrypy.tools的' before_error_response '处理程序

@cherrypy.tools.register('before_error_response', priority=90)
def handleexception():
    cherrypy.response.status = 500
    cherrypy.response.body = ''

别忘了启用它:

tools.handleexception.on = True
import cherrypy
from cherrypy import HTTPError


def handle_an_exception():
    cherrypy.response.status = 500
    cherrypy.response.headers['content-type'] = 'text/plain;charset=UTF-8'
    cherrypy.response.body = b'Internal Server Error'


def handle_a_404(status=None, message=None, version=None, traceback=None):
    cherrypy.response.headers['content-type'] = 'text/plain;charset=UTF-8'
    return f'Error page for 404'.encode('UTF-8')


def handle_default(status=None, message=None, version=None, traceback=None):
    cherrypy.response.headers['content-type'] = 'text/plain;charset=UTF-8'
    return f'Default error page: {status}'.encode('UTF-8')


class Root:
    """Root of the application"""
    _cp_config = {
        # handler for an unhandled exception
        'request.error_response': handle_an_exception,
        # specific handler for HTTP 404 error
        'error_page.404': handle_a_404,
        # default handler for any other HTTP error
        'error_page.default': handle_default
    }

    @cherrypy.expose
    def index(self):
        """Root url handler"""
        raise Exception("an exception")

    @cherrypy.expose
    def simulate400(self):
        raise HTTPError(status=400, message="Bad Things Happened")


cherrypy.quickstart(Root())

测试:

http://127.0.0.1:8080/

http://127.0.0.1:8080/simulate400

http://127.0.0.1:8080/missing

我放弃使用CherryPy并最终使用了以下代码,它使用标准BaseHTTPServer解决了几行问题:

from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
from urlparse import urlparse, parse_qs

class GetHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        url = urlparse(self.path)
        d = parse_qs(url[4])
        if 'c' in d:
            print d['c'][0]
        self.send_response(200)
        self.end_headers()
        return

server = HTTPServer(('localhost', 8080), GetHandler)
server.serve_forever()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM