3

I'm writing a web-application based on the webapp2 framework. I'm using a common base exception for all the errors I'm explicitly throwing, like

class MyBaseException(Exception):
    def __init__(self, status, code, message):
        self.status_code = status
        self.error_code = code
        self.error_message = message

and have a BaseRequestHandler that outputs a simple JSON response for errors, defaulting to a 500/Generic error for unexpected exceptions.

class BaseHandler(webapp2.RequestHandler):
    def handle_exception(self, e, debug):
        logger.exception(e)

        status = e.status_code if isinstance(e, MyBaseException) else 500
        code = e.error_code if isinstance(e, MyBaseException) else 'GENERIC_ERROR'
        message = e.error_message if isinstance(e, MyBaseException) else 'Blah blah blah'

        self.response.set_status(status)
        self.response.content_type = 'application/json'
        self.response.write(json.encode({"code": code, "message": message})

Those isinstance checks look ugly to me, so I'm thinking there has to be a better way. Suggestions?

EDIT What has this to do with downcasting?

In java, my "native" language, I'd do something like

MyBaseException b = (MyBaseException) e;
JSONObject j = new JSONObject();
j.put("error_code", e.getCode());
j.put("error_message", e.getErrorMessage());
...

but python has no explicit type casts so... is it possible to do something like that?

agnul
  • 12,608
  • 14
  • 63
  • 85

1 Answers1

2

The usual Python idiom is to ignore the class of the object altogether, so you'd just do:

status = e.status_code
code = e.error_code
message = e.error_message

This is referred to as duck typing.

If you may need to handle other types of exceptions (where, in your Java example you'd get a ClassCastException) the standard Python idiom is to just wrap the whole thing in a try...catch:

try:
    status = e.status_code
    etc.
catch AttributeError:  # i.e. e doesn't have one of the listed attributes
     status = "500"
     etc.
ig0774
  • 39,669
  • 3
  • 55
  • 57