关于异常捕获try-except:在学java的时候就被教育异常捕获也是java相对c的一大优势,几年下来多少也写了些代码,但异常捕获总只得其形未得其神,在本身这只是让发生错误的程序在没必要要终止时不终止而已。html
关于主动抛出异常raise:前段时间看到robot framework判断测试用例运行失败,是监控本身使用raise主动抛出的异常,这才有了主动抛出异常的概念。java
关于断言assert:前段时间写了个模糊测试工具,而后发现不少能够致使宕机的问题,开发排查后说是新加的断言致使的问题;当时对断言并不太清楚,他们修复问题后也没深刻追究。python
其实这里最主要是说,了解以后发现,try-except、raise和assert其实有至关大的关系,有必要记一记。express
异常捕获没有不少说的,各语言意思都差很少只是书写格式有点区别,咱们直接上示例:函数
def testTryExcept(): try: file_obj = open('myfile.txt') str_var = file_obj.readline() int_var = int(str_var.strip()) # 若是检测到是OSError类异常,进行如下处理 # OSError as err表示给当前捕获到的OSError异常起别名为err;名字叫什么能够是随意的 except OSError as err: print(f"OS error: {err}") # 若是不是OSError检测到是ValueError,进行如下处理 except ValueError: print("Could not convert data to an integer.") # 若是既不是OSError也不是ValueError而是其余异常,进行如下处理 # Exception as e表示给当前捕获到的异常起别名为e;名字叫什么能够是随意的 # 若是不须要打印e,那么Exception as e这部分可省略 # 我本身而言,不会捕获具体的异常类型,即不会像上面同样单独捕获OSError和ValueError,就只写下边这么一个except就完了 except Exception as e: print(f"Unexpected error: {e}") # 不论是否发生异常,finally部分都会执行 # 对于异常捕获而言,finally部分常常能够没有,至少一直以来我都不怎么写 finally: file_obj.close()
在上面的try-except中咱们都是被动等待异常出现而后进行捕获----事实上这些被动等待的异常本质上也是库函数使用raise主动抛出的----咱们彻底可使用raise主动抛出异常,进一步说咱们可使用raise抛出本身定义的异常。工具
主动抛出异常的好处,一是能够抛出在语法上不被认为是异常但在功能上咱们认为是异常的状况(如用户名密码错误等),二是能够自定义本身的异常报错语句更方便异常的定位和排查。测试
注意,主动抛出的异常扔是异常,因此仍能够用try-except来捕获。ui
# 自定义的异常类都要继承Exception类,至少是间接继承Exception类 class PasswordException(Exception): # 在init方法中定义一个password变量 def __init__(self,password): self.password = password def __str__(self): return repr(self.password) def testRaise(): # 主动抛出异常示例 try: username = input("please enter your username:") # 输入的用户名不是admin就抛出异常Exception if username != "admin": raise Exception(f"maybe your privilege is not enough: {username}") # 能够看到打印的是咱们自定义的异常语句 except Exception as e: print(f"{e}") # 主动抛出自定义异常示例 try: password = input("please enter your password:") # 输入的密码不是123456就抛出自定的的PasswordException异常 if password != "123456": raise PasswordException(password) # 咱们自定义的异常有password变量,因此咱们能够直接选择把变量打印出来 except PasswordException as e: print(f"PasswordException: {e.password}") if __name__ == "__main__": testRaise()
更多参见官方文档:https://docs.python.org/3/reference/simple_stmts.html#the-assert-statementspa
assert使用形式以下:debug
assert expression ["," expression]
若是只接一个表达示,那至关于以下:
if __debug__: if not expression: raise AssertionError
若是接两个表达示,那至关于以下:
if __debug__: if not expression1: raise AssertionError(expression2)
其中涉及的__debug__和AssertionError以下:
__debug__:若是程序运行时不带-O参数,则为True;反之则为False。
AssertionError:就是一个继承Exception类的异常类,其源代码在builtins.py中,以下图所示
因此,本质上,assert就是raise的一个宏定义;当前紧接的好个表达示不为True时,就抛出异常。
assert常常用于参数被使用前的检查操做,若是检查未经过则直接抛出异常及早发现错误,避免明显错误的参数还被日后传递。
注意,因为assert本质上仍是raise,因此同样可使用try-except捕获,而不是说断言错误程序就必定会终止。
def testAssert(): try: int_var = int(input("please enter a positive number:")) # 若是输入的数值不大于0,断言失败,抛出异常 assert int_var > 0 except: print(f"sorry, please enter a positive number") print(f"what you enter is: {int_var}") if __name__ == "__main__": testAssert()
参考:
https://www.runoob.com/python3/python3-errors-execptions.html