我编写了一个Django应用程序,它通过Python包装器与第三方API(Disqus,虽然这个细节不重要)进行交互。当服务不可用时,Python包装器会引发异常。
应用程序处理此类异常的最佳方法是禁止它们,以便仍然可以向用户显示页面的其余内容。以下工作正常。
try:
somemodule.method_that_may_raise_exception(args)
except somemodule.APIError:
pass
某些视图包含多个此类调用。是否将每个调用包装在try /中除了抑制可能异常的最佳方法之外?
答案 0 :(得分: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)
...
答案 1 :(得分:1)
某些视图包含多个此类调用。是否将每个调用包装在try /中除了抑制可能异常的最佳方法之外?
您可以将API调用包装在另一个函数中。说:
def make_api_call(*args, **kwargs):
try:
return somemodule.method_that_may_raise_exception(*args, **kwargs)
except somemodule.APIError:
log.warn("....")
可以在每个视图中调用此函数而不是try/except
块。这至少可以减少您编写的代码行数,并为处理此类异常提供一个共同的位置。
<强>更新强>
@Yirirou是对的。更改代码以添加此良好实践。