如何抑制第三方服务不可用时引发的异常?
我写了一个Django应用,它通过一个Python封装与一个第三方API(Disqus,虽然这个细节不重要)进行交互。当这个服务不可用时,Python封装会抛出一个异常。
处理这种异常的最佳方式是让它们不影响用户,这样页面的其他内容仍然可以显示给用户。下面的代码可以很好地实现这一点。
try:
somemodule.method_that_may_raise_exception(args)
except somemodule.APIError:
pass
有些视图包含多个这样的调用。把每个调用都放在try/except里面,是处理可能出现的异常的最佳方法吗?
2 个回答
1
某些视图中包含多个这样的调用。把每个调用都放在try/except里,是否是抑制可能出现的错误的最好方法呢?
你可以把API调用放在另一个函数里。比如:
def make_api_call(*args, **kwargs):
try:
return somemodule.method_that_may_raise_exception(*args, **kwargs)
except somemodule.APIError:
log.warn("....")
这个函数可以代替每个视图中的try/except
块来调用。这样至少可以减少你写的代码行数,并且提供一个统一的地方来处理这些错误。
更新
@Yorirou说得对。正在修改代码以加入这个好习惯。
2
在视图中直接进行API调用并不是个好主意。你应该考虑创建一个单独的模块来处理这些事情。
比如,当我制作Facebook应用时,我会创建一个publish.py
文件,用来存放所有“发布到直播”的调用。这个模块里的函数命名是根据它们应该被调用的时机来命名的。例如:
# publish.py
def authorise_application(user):
# API call "User joined app."
def post_anwser(anwser):
# API call "User posted anwser to quiz".
这样一来,你的视图代码就会非常简洁:
# views.py
def post_anwser(request):
...
if form.is_valid():
form.save()
publish.post_anwser(form.instance)
当你以这种方式组织代码时,你可以创建一个装饰器来忽略异常:
# 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".
你还可以创建一个默认不被“忽略”的函数,并在视图中添加忽略的代码:
# publish.py
def some_function(user, message):
pass
# views.py
def my_view():
...
publish.ignore_api_error(publish.some_function)(user, message)
...