抑制第三方服务不可用时引发的异常的最佳方法是什么?

时间:2010-09-11 06:35:38

标签: python django exception-handling

我编写了一个Django应用程序,它通过Python包装器与第三方API(Disqus,虽然这个细节不重要)进行交互。当服务不可用时,Python包装器会引发异常。

应用程序处理此类异常的最佳方法是禁止它们,以便仍然可以向用户显示页面的其余内容。以下工作正常。

try:
    somemodule.method_that_may_raise_exception(args)
except somemodule.APIError:
    pass

某些视图包含多个此类调用。是否将每个调用包装在try /中除了抑制可能异常的最佳方法之外?

2 个答案:

答案 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是对的。更改代码以添加此良好实践。