在我的程序中,我有一个处理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
被用于如此多的功能,不得不经常重复尝试除了语句错误,好像它应该在函数getFromAPI
。但是,由于其他functionone
到function_n
都会根据是否出现错误而返回不同的内容,因此我无法在getFromAPI
内找到处理该问题的方法,除非有是getFromAPI
迫使它的父函数返回的一种方式,而不是在父函数中显式调用return。
如果做不到,是否可以更好地实现我尝试做的事情,或者我注定要继续重复尝试除了语句?
答案 0 :(得分:8)
写一个像这样的装饰者
def catchAPIException(func):
def wrapper(*args, **kwargs)
try:
return func(*args, **kwargs)
except getFromAPIException as e:
return handleException(e)
return wrapper
然后你的functionone
等看起来像
@catchAPIException
def functionone():
...
data = getFromAPI(url)
...
# formatting data specific to functionone
return formatted_data
但是你想要提出一个非常具体的自定义异常,这样你的装饰者只会抓住相关的。或许你应该创建一些可以不同方式处理的不同异常。
如果不同的函数想要以自定义方式格式化异常,则装饰器可以传递另一个实际用于格式化它的函数。即将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
然后对默认异常处理程序感到满意的函数声明如下:
@catchAPIException
def function1():
...
具有更多特定需求的其他人可以这样做:
def customExceptionHandler(e):
...
@catchAPIException(customExceptionHandler)
def function2():
...
如果您不熟悉装饰器,这里有一个reasonable tutorial并且还有Python文档,尽管它们没有明确的部分。