我有一个类,可以将API引发的低级异常转换成高级异常。该类充满了复杂的、重复的错误处理逻辑。我正在寻找减少此重复性的Pythonic方式。
这里是一个人为制造的例子。
class ApiWrapperException(Exception):
pass
class ApiWrapper(object):
def __init__(self, api):
self._api = api
def do_one_thing(self):
print 'do_one_thing stuff before API call'
try:
self._api.do_one_thing()
except ApiException:
print 'ApiWrapper caught an ApiException. Doing complicated error handling logic. Raising a different exception.'
raise ApiWrapperException
print 'do_one_thing stuff after API call'
def do_another_thing(self):
print 'do_another_thing stuff before API call'
try:
self._api.do_another_thing()
except ApiException:
print 'ApiWrapper caught an ApiException. Doing complicated error handling logic. Raising a different exception.'
raise ApiWrapperException
print 'do_another_thing stuff after API call'
在这个例子中,
ApiWrapper
类将低层级的 ApiException
转换成更好的 ApiWrapperException
。但是有很多重复的代码。选项1:使用函数包装器
我可以将重复的代码放在一个内部函数中,如下所示:
def handle_api_errors(api_callable):
def call(*args, **kwargs):
try:
return api_callable(*args, **kwargs)
except ApiException:
print 'ApiWrapper caught an ApiException. Doing complicated error handling logic. Raising a different exception.'
raise ApiWrapperException
return call
< p > ApiWrapper
类简化了以下内容:
class ApiWrapper(object):
def __init__(self, api):
self._api = api
def do_one_thing(self):
print 'do_one_thing stuff before API call'
handle_api_errors(self._api.do_one_thing)()
print 'do_one_thing stuff after API call'
def do_another_thing(self):
print 'do_another_thing stuff before API call'
handle_api_errors(self._api.do_another_thing)()
print 'do_another_thing stuff after API call'
选项2:使用上下文管理器
我可以将重复的代码放在一个上下文管理器中,像这样:
@contextlib.contextmanager
def handle_api_errors():
try:
yield
except ApiException:
print 'ApiWrapper caught an ApiException. Doing complicated error handling logic. Raising a different exception.'
raise ApiWrapperException
ApiWrapper
类简化了以下内容:
class ApiWrapper(object):
def __init__(self, api):
self._api = api
def do_one_thing(self):
print 'do_one_thing stuff before API call'
with handle_api_errors():
self._api.do_one_thing()
print 'do_one_thing stuff after API call'
def do_another_thing(self):
print 'do_another_thing stuff before API call'
with handle_api_errors():
self._api.do_another_thing()
print 'do_another_thing stuff after API call'
选项三:使用装饰器(由@ZachGates建议)
我可以将重复的代码放在一个装饰器中,像这样:
def handle_api_errors(api_calling_func):
def decorated_func(*args, **kwargs):
try:
api_calling_func(*args, **kwargs)
except ApiException:
print 'ApiWrapper caught an ApiException. Doing complicated error handling logic. Raising a different exception.'
raise ApiWrapperException
return decorated_func
ApiWrapper
类简化了以下操作:
class ApiWrapper(object):
def __init__(self, api):
self._api = api
@handle_api_errors
def do_one_thing(self):
print 'do_one_thing stuff before API call'
self._api.do_one_thing()
print 'do_one_thing stuff after API call'
@handle_api_errors
def do_another_thing(self):
print 'do_another_thing stuff before API call'
self._api.do_another_thing()
print 'do_another_thing stuff after API call'
哪个选项被认为是最符合Python风格的?还有更好的选择吗?