[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.

posted @ 2018-06-14 20:53  郝壹贰叁  阅读(239)  评论(0编辑  收藏  举报