[Advanced Python] Exceptions
Exception
一、常见系统异常
Ref: The definitive guide to Python exceptions
更多内容详见:Python标准异常列表
except OSError 系统错误 except IOError IO错误 except ValueError 值错误:数字转换 except ZeroDivisionError 除数错误 except NameError 命名错误
except TypeError __init__误写成了_init_
-
非异常方案
“输入”的内容不好预测,也是“异常多发地”,故在此用来举例。
while True: reply = input('Enter text:') if reply == 'stop': break elif not reply.isdigit(): # 如果不是数字 print('Bad!' * 8) else: # 如果是数字 num = int(reply) if num < 20: print('low') else: print(num ** 2) print('Bye')
-
异常方案
黑马培训说:根据错误类型捕获异常。
import sys try: f = open('myfile.txt') # --> OSError s = f.readline() i = int(s.strip()) # --> ValueError
except OSError as err: print("OS error: {0}".format(err))
except ValueError: print("Could not convert data to an integer.")
except (RuntimeError, TypeError, NameError) # 如果处理策略一致,统一起来写
pass
except: print("Unexpected error:", sys.exc_info()[0]) # 捕获未知异常 raise
else: # 在try子句没有发生任何异常的时候执行
pass
finally:
pass
[意义何在?]
ref: Python中try…except…else…结构中else的作用?
既然执行到了else,就说明“没有异常发生”。如此,代码更清晰更具有表现力。
try语句必须有一个except或一个finally,else是可选的;但是如果有else,则必须至少有一个except。
二、异常传递
黑马说:异常的传递性
每个函数内都增加异常处理,太辛苦。怎么办?
在 “主程序” 捕获异常即可!
- 抛出异常
使用 raise 语句抛出一个指定的异常。
>>>try: raise NameError('HiThere')
except NameError
print('An exception flew by!', NameError.value) raise
------------------------------------------------------ An exception flew by! Traceback (most recent call last): File "<stdin>", line 2, in ? NameError: HiThere
-
应用场景
step 1, 抛出异常。
def input_password(): pwd = input("input your password: ") if len(pwd) >=8: return pwd
print("raise exception") ex = Exception("密码长度不够") raise ex
step 2, 外围主函数接收到异常。
try: print(input_password()) except Exception as result: print(result)
三、自定义异常
- Custom "异常类"
"异常类" 继承自 Exception 类,可以直接继承,或者间接继承。
>>>class MyError(Exception): def __init__(self, value): self.value = value # 类 Exception 默认的 __init__() 被覆盖 def __str__(self): return repr(self.value)
-------------------------------------------------------
>>> try: raise MyError(2*2)
except MyError as e: print('My exception occurred, value:', e.value)
My exception occurred, value: 4 >>> raise MyError('oops!') Traceback (most recent call last): File "<stdin>", line 1, in ? __main__.MyError: 'oops!'
- Custom "异常基类"
当创建一个模块有可能抛出多种不同的异常时,一种通常的做法是:
(1) 为这个包建立一个基础异常类;
(2) 然后基于这个基础类为不同的错误情况创建不同的子类。
# 有点像接口的感觉
class Error(Exception): """Base class for exceptions in this module.""" pass
------------------------------------------------------------------
# 再定义具体的异常内容 class InputError(Error): """Exception raised for errors in the input. Attributes: expression -- input expression in which the error occurred message -- explanation of the error """ def __init__(self, expression, message): self.expression = expression self.message = message
class TransitionError(Error): """Raised when an operation attempts a state transition that's not allowed. Attributes: previous -- state at beginning of transition next -- attempted new state message -- explanation of why the specific transition is not allowed """ def __init__(self, previous, next, message): self.previous = previous self.next = next self.message = message
当业务复杂时,例如 rest api返回client信息时,会考虑如此。
详见:[Advanced Python] Find exceptions and tell me in the right way
End.