如何抑制第三方服务不可用时引发的异常?

3 投票
2 回答
2485 浏览
提问于 2025-04-16 04:00

我写了一个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)
    ...

撰写回答