在我的程序中,我有一个处理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
虽然我不认为这是错误的,但就其本身而言,因为
getFromAPI
在许多函数中使用,必须不断重复try-except语句感觉是错误的,好像应该在函数getFromAPI
中处理它一样但是,由于另一个functionone
到function_n
都返回不同的内容,这取决于是否引发了错误,所以我看不到从getFromAPI
中处理这个问题的方法,除非有一种方法可以让getFromAPI
强制它的父函数返回,而不在父函数中显式调用return。如果做不到这一点,是否有更好的方法来实现我所要做的事情,或者我注定要不断重复除声明之外的尝试?
最佳答案
写一个这样的装饰
def catchAPIException(func):
def wrapper(*args, **kwargs)
try:
return func(*args, **kwargs)
except getFromAPIException as e:
return handleException(e)
return wrapper
那么你的等看起来就像
@catchAPIException
def functionone():
...
data = getFromAPI(url)
...
# formatting data specific to functionone
return formatted_data
但是您希望引发一个非常特定的自定义异常,以便您的装饰器只捕获相关的异常或者您应该创建一些不同的异常,这些异常可以用不同的方式处理。
如果不同的函数希望以自定义方式格式化异常,则可以向decorator传递另一个实际用于格式化异常的函数即将
functionone
作为handleException
的参数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
然后,对默认异常处理程序满意的函数声明如下:
@catchAPIException
def function1():
...
其他有更具体需求的人可以这样做:
def customExceptionHandler(e):
...
@catchAPIException(customExceptionHandler)
def function2():
...
如果您不熟悉decorators,这里有一个reasonable tutorial和一些Python文档,尽管它们没有显式的部分。