54

I am designing a RESTful API using Python and Flask. As expected, the API needs to receive an API request and return data if all goes well, but in the instance of an error, it needs to fail softly and return the proper error. I typically raise exceptions when an error results, but in this case I need to return the error message to the user (try-catch block?).

The way I am currently dealing with errors is to have my functions return both the data and an error, and to check for the data at each level, finally returning either the data or the error to the caller of the API function.

The problem with this is that it can get cumbersome when there are several levels of function calls, requiring my functions to pass data and errors several times and perform checks each time.

Is there a better way to do this? What are some improvements I could make to make the error propagation more simple and elegant?

Here is an example of the way I'm currently returning errors:

def get_data()
    data1, error = get_some_data() # function not shown
    if data1 is None:
         return None, "could not retrieve data1"
    data2, error = get_some_other_data() # function not shown
    if data2 is None:
         return None, "could not retrieve data2"
    return (data1, data2), None

@app.route("/api/method", methods=['GET'])
def method():
    data, error = get_data()
    if data is None:
        if error is None:
            error = "unknown error"
        return json.dumps({ "error": error }), 500
    return json.dumps({ "data": data }), 200
5
  • Why don't you use exceptions? Commented Sep 27, 2012 at 21:34
  • 1
    Because that will return an internal server error without a proper message in json format. Think Facebook API style. Commented Sep 27, 2012 at 21:43
  • I kind of agree with @thg435. Seems to me that a try...except would clean up your "method" a bit. You would just move your error handling block to the "except" block and can still return the error message. This is how I do it in Django with Ajax calls. Also, I don't have any experience with Flask, but if this is a RESTful(ish) API. and it appears to be because you are going a "GET", you should return an appropriate status code. 200 if things are ok. Or a 4XX or 500 (depending on what the underlying problem is). Commented Sep 27, 2012 at 21:45
  • My bad on the status code, I forgot to include that in my example. I just fixed it. The default is to return a status code of 200. Commented Sep 27, 2012 at 21:46
  • Ah ok, I believe I misunderstood at first. I could try that as well. Not sure whether that is more or less elegant than J.F.'s solution. Commented Sep 27, 2012 at 21:57

2 Answers 2

47

You could use abort(http_code) to return an appropriate http code to the client or just raise a non-http exception. And use @app.errorhandler() decorator to provide a custom handler for http errors and arbitrary exceptions. You could also use an ordinary try/except block where you are ready to handle an exception. Python is not Go you can use exceptions.

Sign up to request clarification or add additional context in comments.

3 Comments

I like the raise non-http exception plus @app.errorhandler() idea. I'm going to look into it in the Flask documentation and then see how well it works.
+1 - errorhandler and throwing exceptions really is the correct answer
Flask docs explicitly recommend avoiding the use of abort in favour of writing your own exception class and error handler -> flask.pocoo.org/docs/0.12/patterns/apierrors
4

Maybe the Flask API is more suitable for your needs, as it is particularly designed for RESTful APIs.

It has better exception handling than Flask, see: http://www.flaskapi.org/api-guide/exceptions/

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.