Python:有没有办法强制父函数返回?

ech*_*ion 3 python exception

在我的程序中,我有一个处理requests调用的函数,并返回已处理的调用或引发异常.许多其他函数使用此函数,但是,我遇到的问题是如何处理可能引发的异常.目前它设置如此(简化):

def getFromAPI(url):
    # create variable headers
    r = requests.get(url, headers=headers)
    if r.status_code == 404:
        raise Exception("Error raised")
    else:
        #process data
        return data

def functionone():
    ...
    try:
        data = getFromAPI(url)
    except Exception as e:
        return handleException(e) 
        #handles problems, returns exception-formatted data

    ...
    # formatting data specific to functionone
    return formatted_data

def functiontwo():
    ...
    try:
        data = getFromAPI(url)
    except Exception as e:
        return handleException(e) 
        #handles problems, returns exception-formatted data

    ...
    # formatting data specific to functiontwo
    return formatted_data

def functionthree():
    ...
    #similar to functionone and functiontwo
Run Code Online (Sandbox Code Playgroud)

虽然我认为这本身并不错,但由于getFromAPI在很多函数中使用,因此不得不经常重复try除了语句错误,就好像它应该在函数内处理一样getFromAPI.但是,由于另一个functionone通过function_n所有返回不同的东西取决于是否引发了错误,我无法看到从内部处理它的方法getFromAPI,除非有一种方法getFromAPI强制它的父函数返回,而不显式调用返回父函数.

如果不这样做,是否有更好的实现我正在尝试做的事情,或者我注定要继续重复尝试除了语句?

kdo*_*pen 8

写一个这样的装饰器

def catchAPIException(func):
    def wrapper(*args, **kwargs)
        try:
            return func(*args, **kwargs)
        except getFromAPIException as e:
            return handleException(e)
    return wrapper
Run Code Online (Sandbox Code Playgroud)

然后你的functionone等等看起来像

@catchAPIException
def functionone():
    ...
    data = getFromAPI(url)
    ...
    # formatting data specific to functionone
    return formatted_data
Run Code Online (Sandbox Code Playgroud)

但是你想要提出一个非常具体的自定义 Exception,这样你的装饰器才会捕获相关的.或许您应该创建一些可以不同方式处理的不同异常.

如果不同的函数想要以自定义方式格式化异常,则装饰器可以传递另一个实际用于格式化它的函数.即做handleException一个参数catchAPIException

def catchAPIException(exceptionHandler = handleException):
    def real_decorator(func):
        def wrapper(*args, **kwargs)
            try:
                return func(*args, **kwargs)
            except getFromAPIException as e:
                return exceptionHandler(e)
        return wrapper
    return real_decorator
Run Code Online (Sandbox Code Playgroud)

然后,对默认异常处理程序感到满意的函数声明如下:

@catchAPIException
def function1():
    ...
Run Code Online (Sandbox Code Playgroud)

具有更多特定需求的其他人可以这样做:

def customExceptionHandler(e):
    ...

@catchAPIException(customExceptionHandler)
def function2():
    ...
Run Code Online (Sandbox Code Playgroud)

如果你不熟悉装饰器,这里有一个合理的教程,虽然他们没有关于它们的明确部分,但也有Python文档.