How to catch all exceptions with CherryPy?

妖精的绣舞 提交于 2019-12-05 09:56:59

Docs somehow seem to miss this section. This is what I found while looking for detailed explanation for custom error handling from the source code.

Custom Error Handling

Anticipated HTTP responses

The 'error_page' config namespace can be used to provide custom HTML output for expected responses (like 404 Not Found). Supply a filename from which the output will be read. The contents will be interpolated with the values %(status)s, %(message)s, %(traceback)s, and %(version)s using plain old Python string formatting.

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

Beginning in version 3.1, you may also provide a function or other callable as an error_page entry. It will be passed the same status, message, traceback and version arguments that are interpolated into templates

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})

Also in 3.1, in addition to the numbered error codes, you may also supply error_page.default to handle all codes which do not have their own error_page entry.

Unanticipated errors

CherryPy also has a generic error handling mechanism: whenever an unanticipated error occurs in your code, it will call Request.error_response to set the response status, headers, and body. By default, this is the same output as HTTPError(500). If you want to provide some other behavior, you generally replace "request.error_response".

Here is some sample code that shows how to display a custom error message and send an e-mail containing the error

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

Note that you have to explicitly set response.body and not simply return an error message as a result.

Choose what's most suitable for you: Default Methods, Custom Error Handling.

I don't think you should use BaseHTTPServer. If your app is that simple, just get a lightweight framework (e. g. Flask), even though it might be a bit overkill, OR stay low level but still within the WSGI standard and use a WSGI-compliant server.

Derek Litz

CherryPy IS catching your exception. That's how it returns a valid page to the browser with the caught exception.

I suggest you read through all the documentation. I realize it isn't the best documentation or organized well, but if you at least skim through it the framework will make more sense. It is a small framework, but does almost everything you'd expect from a application server.

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 

See this for the example in the documentation on the page mentioned above for further reference.

You can simply use a try/except clause:

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

This will catch every single error. But if you want to catch only cherrypy._cperror:

from cherrypy import _cperror

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

Hope this helps!

Though this was the one of the top results when I searched for cherrypy exception handling, accepted answer did not fully answered the question. Following is a working code against 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}

Note the method signature. Without this signature your method will not get invoked.Following are the contents of method parameters,

  • status : HTTP status and a description
  • message : Message attached to the exception
  • traceback : Formatted stack trace
  • version : Cherrypy version

Maybe you could use a 'before_error_response' handler from cherrypy.tools

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

And don't forget to enable it:

tools.handleexception.on = True

I gave up using CherryPy and ended up using the follwing code, which solves the issue in a few lines with the standard 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()
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!