如何处理未处理的异常?
作者:互联网
我正在清理API库,并尝试找出处理未处理异常的最佳方法.
现在,该库几乎捕获了API可能出错的所有内容-凭据错误,服务器错误,urllib2错误,httplib错误等.这将存在一些极端情况.
我当前的想法是99%的库用户不关心异常本身,他们只关心API调用失败.只有开发人员才会关心该异常.
这使我想到了这个解决方案:
class ApiError(Exception):
pass
class ApiUnhandledError(ApiError):
pass
API的已知问题会引发ApiError或特定的子类.
其他所有内容都会引发ApiUnhandledError,并保留原始错误,用户可以捕获或忽略该错误.
try:
stuff
except urllib2.UrlError , e :
raise ApiError(raised=e)
except Exception as e :
raise ApiUnhandledError(raised=e)
这听起来像是确保用户只知道通过/失败,同时开发人员可以维持支持方法的好方法吗?
更新资料
基于最佳实践的共识,我不会对此加以限制.
最初的目标是允许人们这样做:
try:
stuff_a
other_stuff
even_more_stuff
api.proxy(url)
again_stuff
again_others
except api.ApiUnhandledError , e :
handle error
except api.ApiError , e :
handle error
except Stuff , e :
other error
except:
raise
在该示例中,用户只需捕获ApiError(以及可选的ApiUnhandledError或任何其他子类)
我认为这将比每个具有自己的块的api交互都更可取:
try:
stuff_a
other_stuff
even_more_stuff
try:
api.proxy(url)
except api.ApiError , e :
handle error
except CatchSomething1 , e :
handle error
except CatchSomething2 , e :
handle error
except CatchSomething3 , e :
handle error
except CatchSomething4 , e :
handle error
except:
raise
again_stuff
again_others
except Stuff , e :
other error
except:
raise
当处理urllib2时,我似乎每天都发现一个新的异常.这些异常往往会变得非常漫长且难以维护.
解决方法:
如果您的图书馆提出了一个您没有预见到并且您没有处理的异常,那就这样.这可能是库错误的标志,否则将被忽略.如果可以明确指出错误的原因,则可以捕获并重新启动(例如,在authenticator方法中捕获socket.error并重新启动AuthenticationFailedError),但是对库用户(谁是程序员自己).
用户不应该尝试处理或消除直接来自库内部的错误(即,不是您的API的一部分-大致上,不是您编写或提出的错误),因为它们是该代码段的内部内容.如果图书馆作者忘了处理它们或赶上并重新启动更具体的一个,那是一个错误,应该报告.如果函数对输入进行了假设(例如,针对速度),则应在API参考中明确说明,并且任何违规都是用户的错.
在Python2中,只能引发继承自BaseException的经典类或新样式类,而在Python3中,经典类已消失,因此您的库可能引发的任何事情都必须从BaseException继承.用户通常要处理的任何异常(不包括SystemExit,GeneratorExit,KeyboardInterrupt等,它们都有特殊情况)必须从Exception继承.尝试提高时会报告未这样做:
Python3:
>>> class Test:
... pass
...
>>> raise Test()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: exceptions must derive from BaseException
Python2:
>>> class Test(object):
... pass
...
>>> raise Test()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: exceptions must be old-style classes or derived from BaseException, not Test
>>>
就是说,您不需要将异常包装在UnhandledException容器内,只需使代码中的所有异常都继承自Exception.屏蔽失败是一种不好的做法(您不应该鼓励这样做),但是懒惰的用户仍然可以利用Exception基类的继承,并使用以下方法捕获所有未处理的异常:
try:
yourapi.call_me()
except APIKnownError as error:
report(error)
except Exception as error:
pass
# Or whatever
值得注意的是,Python提供了一个warnings
模块来报告“程序中的某些条件,该条件(通常)不保证引发异常并终止程序”.
说到应用程序框架(不是库),我非常喜欢Tornado方法:它将记录所有未处理的异常,如果错误不严重,则继续执行.我认为该决定应由最终用户决定.
标签:exception-handling,python 来源: https://codeday.me/bug/20191123/2066795.html