14.8 创建自定义异常¶
问题¶
åœ¨ä½ æž„å»ºçš„åº”ç”¨ç¨‹åº�ä¸ï¼Œä½ 想将底层异常包装æˆ�自定义的异常。
解决方案¶
创建新的异常很简å�•——定义新的类,让它继承自 Exception (或者是任何一个已å˜åœ¨çš„异常类型)。
ä¾‹å¦‚ï¼Œå¦‚æžœä½ ç¼–å†™ç½‘ç»œç›¸å…³çš„ç¨‹åº�ï¼Œä½ å�¯èƒ½ä¼šå®šä¹‰ä¸€äº›ç±»ä¼¼å¦‚下的异常:
class NetworkError(Exception):
pass
class HostnameError(NetworkError):
pass
class TimeoutError(NetworkError):
pass
class ProtocolError(NetworkError):
pass
ç„¶å�Žç”¨æˆ·å°±å�¯ä»¥åƒ�é€šå¸¸é‚£æ ·ä½¿ç”¨è¿™äº›å¼‚å¸¸äº†ï¼Œä¾‹å¦‚ï¼š
try:
msg = s.recv()
except TimeoutError as e:
...
except ProtocolError as e:
...
讨论¶
自定义异常类应该总是继承自内置的 Exception 类,
或者是继承自那些本身就是从 Exception 继承而�的类。
尽管所有类å�Œæ—¶ä¹Ÿç»§æ‰¿è‡ª BaseException ï¼Œä½†ä½ ä¸�应该使用这个基类æ�¥å®šä¹‰æ–°çš„异常。
BaseException 是为系统退出异常而�留的,比如 KeyboardInterrupt 或 SystemExit
以�其他那些会给应用��信�而退出的异常。
å› æ¤ï¼Œæ�•获这些异常本身没什么æ„�义。
è¿™æ ·çš„è¯�,å�‡å¦‚ä½ ç»§æ‰¿ BaseException
å�¯èƒ½ä¼šå¯¼è‡´ä½ 的自定义异常ä¸�会被æ�•获而直接å�‘é€�ä¿¡å�·é€€å‡ºç¨‹åº�è¿�行。
在程åº�ä¸å¼•入自定义异常å�¯ä»¥ä½¿å¾—ä½ çš„ä»£ç �æ›´å…·å�¯è¯»æ€§ï¼Œèƒ½æ¸…晰显示è°�应该阅读这个代ç �。 还有一ç§�设计是将自定义异常通过继承组å�ˆèµ·æ�¥ã€‚在å¤�æ�‚应用程åº�ä¸ï¼Œ 使用基类æ�¥åˆ†ç»„å�„ç§�异常类也是很有用的。它å�¯ä»¥è®©ç”¨æˆ·æ�•获一个范围很窄的特定异常,比如下é�¢è¿™æ ·çš„:
try:
s.send(msg)
except ProtocolError:
...
ä½ è¿˜èƒ½æ�•获更大范围的异常,就åƒ�下é�¢è¿™æ ·ï¼š
try:
s.send(msg)
except NetworkError:
...
å¦‚æžœä½ æƒ³å®šä¹‰çš„æ–°å¼‚å¸¸é‡�写了 __init__() 方法,
ç¡®ä¿�ä½ ä½¿ç”¨æ‰€æœ‰å�‚数调用 Exception.__init__() ,例如:
class CustomError(Exception):
def __init__(self, message, status):
super().__init__(message, status)
self.message = message
self.status = status
看上去有点奇怪,ä¸�过Exception的默认行为是接å�—æ‰€æœ‰ä¼ é€’çš„å�‚数并将它们以元组形å¼�å˜å‚¨åœ¨ .args 属性ä¸.
很多其他函数库和部分Python库默认所有异常都必须有 .args 属性,
å› æ¤å¦‚æžœä½ å¿½ç•¥äº†è¿™ä¸€æ¥ï¼Œä½ 会å�‘çŽ°æœ‰äº›æ—¶å€™ä½ å®šä¹‰çš„æ–°å¼‚å¸¸ä¸�会按照期望è¿�行。
为了演示 .args 的使用,考虑下下�这个使用内置的 RuntimeError` 异常的交互会�,
注æ„�看raiseè¯å�¥ä¸ä½¿ç”¨çš„å�‚æ•°ä¸ªæ•°æ˜¯æ€Žæ ·çš„ï¼š
>>> try:
... raise RuntimeError('It failed')
... except RuntimeError as e:
... print(e.args)
...
('It failed',)
>>> try:
... raise RuntimeError('It failed', 42, 'spam')
... except RuntimeError as e:
... print(e.args)
...
('It failed', 42, 'spam')
>>>
关于创建自定义异常的更多信�,请�考`Python官方文档 <https://docs.python.org/3/tutorial/errors.html>`_