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.
精彩评论