简体   繁体   English

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

[英]Best way to suppress exceptions raised when third-party service is unavailable?

I've written a Django application which interacts with a third-party API (Disqus, although this detail is unimportant) via a Python wrapper. 我编写了一个Django应用程序,它通过Python包装器与第三方API(Disqus,虽然这个细节不重要)进行交互。 When the service is unavailable, the Python wrapper raises an exception. 当服务不可用时,Python包装器会引发异常。

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.APIError:
    pass

Certain views contain several such calls. 某些视图包含多个此类调用。 Is wrapping each call in try/except the best way to suppress possible exceptions? 在try /中包装每个调用除了抑制可能异常的最佳方法之外?

Making API calls from views is not so good idea. 从视图进行API调用并不是一个好主意。 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. 当我制作Facebook应用程序时,我创建了publish.py文件来存储所有“发布到实时流”的调用。 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? 在try /中包装每个调用除了抑制可能异常的最佳方法之外?

You can wrap the API call inside another function. 您可以将API调用包装在另一个函数中。 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. 可以在每个视图中调用此函数而不是try/except块。 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. @Yirirou是对的。 Changing code to add this good practice. 更改代码以添加此良好实践。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM