开发者

Best way to suppress exceptions raised when third-party service is unavailable?

I've written a Django application which interacts with a third-party API (Disqus, although this detail is unimportant) via a Python wrapper. When the service is unavailable, the Python wrapper raises an exception.

The best way for the application to handle such exceptions is to suppress them so that the rest of the page's content can still be displayed to the user. The following works fine.

try:
    somemodule.method_that_may_raise_exception(args)
except somemodule.AP开发者_JS百科IError:
    pass

Certain views contain several such calls. Is wrapping each call in try/except the best way to suppress possible exceptions?


Making API calls from views is not so good idea. You should probably create another module, that does the job.

ie. when I make Facebook apps I create publish.py file to store all "publish to live stream" calls. Functions in that module are named based on when they should be called. Ie.:

# publish.py
def authorise_application(user):
    # API call "User joined app."

def post_anwser(anwser):
    # API call "User posted anwser to quiz".

Then your views are very clean:

# views.py
def post_anwser(request):
    ...
    if form.is_valid():
        form.save()
        publish.post_anwser(form.instance)

When you have your code organised that way, you can create decorator for ignoring exceptions:

# publish.py
def ignore_api_error(fun):
    def res(*args, **kwargs):
        try:
            return fun(*args, **kwargs):
        except someservice.ApiError:
            return None
    return res

@ignore_api_error
def authorised_application(user):
    # API call "User joined app."

@ignore_api_error
def posted_anwser(user, anwser):
    # API call "User posted anwser to quiz".

Also you can create function, that is not "ignored" by default, and add ignore code in view:

# publish.py
def some_function(user, message):
    pass

# views.py
def my_view():
    ...
    publish.ignore_api_error(publish.some_function)(user, message)
    ...


Certain views contain several such calls. Is wrapping each call in try/except the best way to suppress possible exceptions?

You can wrap the API call inside another function. Say:

def make_api_call(*args, **kwargs):
    try:
        return somemodule.method_that_may_raise_exception(*args, **kwargs)
    except somemodule.APIError:
        log.warn("....")           

This function can be called instead of the try/except block in each view. This will at least serve to reduce the number of lines of code you write and provide a common place for handling such exceptions.

Update

@Yorirou is correct. Changing code to add this good practice.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜