Pergunta

Given this simple Bottle code:

def bar(i):
    if i%2 == 0:
        return i
    raise MyError

@route('/foo')
def foo():
    try:
        return bar()
    except MyError as e:
        response.status_code = e.pop('status_code')
        return e

How would one write Bottle middleware so the same exception handling is done implicitly, so that code like this can work identically to above:

@route('/foo')
def foo():
    return bar()
Foi útil?

Solução

You can do this elegantly with a plugin leveraging abort:

from bottle import abort

def error_translation(func):
    def wrapper(*args,**kwargs):
        try:
            func(*args,**kwargs)
        except ValueError as e:
            abort(400, e.message)
    return wrapper

app.install(error_translation)

Outras dicas

Bottle respect the wsgi spec. You can use a classic wsgi middleware

from bottle import route, default_app, run, request

# push an application in the AppStack
default_app.push()


@route('/foo')
def foo():
    raise KeyError()


# error view
@route('/error')
def error():
    return 'Sorry an error occured %(myapp.error)r' % request.environ


# get the bottle application. can be a Bottle() instance too
app = default_app.pop()
app.catchall = False


def error_catcher(environ, start_response):
    # maybe better to fake the start_response callable but this work
    try:
        return app.wsgi(environ, start_response)
    except Exception as e:
        # redirect to the error view if an exception is raised
        environ['PATH_INFO'] = '/error'
        environ['myapp.error'] = e
        return app.wsgi(environ, start_response)


# serve the middleware instead of the applicatio
run(app=error_catcher)

You can use this instead:

from bottle import error, run, route

@error(500)
def error_handler_500(error):
    return json.dumps({"status": "error", "message": str(error.exception)})

@route("/")
def index():
    a = {}
    a['aaa']

run()
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top