一、异常
当Python解释器遇到一个无法预期的程序行为的时候,就会输出一个异常(exception),eg:除以零或者打开不存在的文件等。当Python解释器遇到异常情况的时候,它会停止程序的运行,然后显示一个追踪(traceback)信息。
二、常见错误和异常
2.1 语法错误(SyntaxError)
2.1.1 缺少冒号
在if、elif、else、for、while、class、def声明末尾都需要添加“:”,如果没有添加就会出现 SyntaxError: invalid syntax 的错误
2.1.2 将赋值运算符=与比较运算符== 混淆
2.1.3 在字符串首尾没有加引号
2.1.4 使用关键字作为变量名
Pytho关键字不能作为变量名。
import keywordprint(keyword.kwlist)['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']
2.1.5 误用自增或自减运算符
2.1.6 代码结构的缩进错误
if __name__ == "__main__"coor = coordination()coor.position()##结果if __name__ == "__main__"^SyntaxError: invalid syntax##缩进错误import keywordprint(keyword.kwlist)##结果print(keyword.kwlist)^IndentationError: unexpected indent
2.2 除零错误(ZeroDivisionError)
print(25/0)##结果print(25/0)ZeroDivisionError: division by zero
2.3 变量名错误(NameError)
命令或程序中访问的变量未经定义而直接使用。
print(numbers)##结果print(numbers)NameError: name 'numbers' is not defined
2.4 操作类型错误(TypeError)
2.4.1 修改元组和字符串的值
元组和字符串的元素值是不能进行修改的,修改的话们就会提示错误
##修改元组的值aa = (100,220,300)aa[1]=300aa[1]=300TypeError: 'tuple' object does not support item assignment##修改字符串的值aa ="千里黄云白日曛"aa[1]=1aa[1]=1TypeError: 'str' object does not support item assignment
2.4.2 连接字符串和非字符串
aa ="千里黄云白日曛"list=[1,2,3,4]print(aa+list)##结果print(aa+list)TypeError: can only concatenate str (not "list") to str
2.4.3 方法的第一个参数没有添加self参数
class GS():def myMethod():print("这个")g = GS()g.myMethod()##结果g.myMethod()TypeError: myMethod() takes 0 positional arguments but 1 was given
2.4.4 不符合表达式中运算符的运算规则或者函数参数类型的错误
print(len(123456))##结果TypeError: object of type 'int' has no len()
2.5 下标越界错误(IndexError)
请求的索引下标超过了序列的范围而造成的错误。
a= [1,5,3,8,6,8]print(a[100])##结果print(a[100])IndexError: list index out of range
2.6 打开文件错误(FileNotFoundError)
fp= open("1.txt",'r+')FileNotFoundError: [Errno 2] No such file or directory: '1.txt'
三、内置异常
https://docs.python.org/3.7/library/exceptions.html#exception-hierarchy
BaseException ##所有异常的基类+-- SystemExit ##Python解释器请求退出+-- KeyboardInterrupt ##用户执行中断,ctrl+c+-- GeneratorExit ##生成器发生异常通知退出+-- Exception ##常规错误的基类+-- StopIteration ##迭代器没有更多的值+-- StopAsyncIteration ## 必须由一个 asynchronous iterator 对象的 __anext__() 方法来引发以停止迭代操作+-- ArithmeticError ##所有数值计算错误的基类| +-- FloatingPointError ##浮点计算错误| +-- OverflowError ##数值运算超出最大限制| +-- ZeroDivisionError ##除零(或取模)错误+-- AssertionError ##断言语句失败,在assert语句运行失败的时候输出+-- AttributeError ##对象没有这个属性+-- BufferError ##当与缓冲区相关的操作无法执行时将被引发+-- EOFError ##没有内建输入,到达EOF标记+-- ImportError ##导入模块/对象失败| +-- ModuleNotFoundError ##模块未找到+-- LookupError ##无效数据查询的基类| +-- IndexError ##序列中没有此索引(index)| +-- KeyError ##映射中没有这个键+-- MemoryError ##内存溢出错误+-- NameError ##未命名/初始化对象(没有属性)| +-- UnboundLocalError ##访问未初始化的本地变量+-- OSError ##操作系统错误| +-- BlockingIOError ##当一个操作会被某个设置为非阻塞操作的对象(例如套接字)所阻塞时将被引发| +-- ChildProcessError ##当一个子进程上的操作失败时将被引发| +-- ConnectionError ##与连接相关问题的基类| | +-- BrokenPipeError ##当试图写入另一端已被关闭的管道,或是试图写入已关闭写入的套接字时将被引发| | +-- ConnectionAbortedError ##当连接尝试被对端中止时将被引发| | +-- ConnectionRefusedError ##当连接尝试被对端拒绝时将被引发| | +-- ConnectionResetError ##当连接被对端重置时将被引发| +-- FileExistsError ##当试图创建一个已存在的文件或目录时将被引发| +-- FileNotFoundError ## 当所请求的文件或目录不存在时将被引发| +-- InterruptedError ##当系统调用被输入信号中断时将被引发| +-- IsADirectoryError ##当请求对一个目录执行文件操作将被引发| +-- NotADirectoryError ##当请求对一个非目录对象执行目录操作时将被引发| +-- PermissionError ##当在没有足够操作权限的情况下试图执行某个操作时将被引发| +-- ProcessLookupError ## 当给定的进程不存在时将被引发| +-- TimeoutError ## 当系统调用超时的时候被引发+-- ReferenceError ##弱引用(weak reference)试图访问已经垃圾回收的对象+-- RuntimeError ##一般的运行时错误| +-- NotImplementedError ##尚未实现的方法| +-- RecursionError ##它会在解释器检测发现超过最大递归深度时被引发+-- SyntaxError ##语法错误| +-- IndentationError ##缩进错误| +-- TabError ##Tab和空格混用+-- SystemError ##一般的解释器系统错误+-- TypeError ##对类型无效的操作+-- ValueError ##传入无效的参数| +-- UnicodeError ##当发生与 Unicode 相关的编码或解码错误时将被引发| +-- UnicodeDecodeError ##Unicode解码的时候的错误| +-- UnicodeEncodeError ##Unicode编码的时候的错误| +-- UnicodeTranslateError ##Unicode转换的时候的错误+-- Warning ##警告的基类+-- DeprecationWarning ##关于被弃用的特征的警告+-- PendingDeprecationWarning ##对于已过时并预计在未来弃用,但目前尚未弃用的特性相关警告的基类+-- RuntimeWarning ##可疑的运行时行为的警告+-- SyntaxWarning ##可疑的语法的警告+-- UserWarning ##用户代码生成警告+-- FutureWarning ##关于构造将来语义会有改变的警告+-- ImportWarning ##与在模块导入中可能的错误相关的警告的基类+-- UnicodeWarning ##与 Unicode 相关的警告的基类+-- BytesWarning ##与 bytes 和 bytearray 相关的警告的基类+-- ResourceWarning ##与资源使用相关的警告的基类
四、try 异常处理
4.1 try……expect语句
try:<被检测的程序代码>expect <异常类型>:<异常处理的程序代码>
try语句中包含可能出现异常的代码。
except语句用来捕获异常的类中并执行异常处理。
ps:异常的名称也可以时空白的,表示此except语句处理所有类型的异常,即全捕获。异常的名称可以时一个也可以是多个。可以使用不同的expect语句处理不同的异常。
用户可以在expect语句内使用pass语句来忽略所发生的异常。
使用try……expect语句的工作原理:
1.如果try子句中被检测的程序代码有异常且被expect子句通过异常类型捕获到,则执行except子句中的异常处理程序代码
2.如果try子句中被检测到的程序代码没有发生异常,则不执行expect子句中的异常程序处理代码,程序继续向下执行
3.如果try子句中被检测到的程序代码有异常发生,但expect子句没有捕获到该异常,则程序会终止执行,并将该异常显示给最终用户。
try:12/0except ZeroDivisionError:print("数值不能除以0")##结果数值不能除以0try:12/0except ZeroDivisionError:passprint("--------")##结果--------
4.2 try……expect……else语句
当try语句没有检测到异常的时候,执行else子句的代码
try:<被检测的程序代码>expect <异常类型>:<异常处理的程序代码>else:<正常处理的程序代码>
如果try语句中的语句有错位u,如果错误类型与except语句捕获的错误类型不符,则不执行except子句中的代码,也不执行else子句中的代码,而是程序终止运行,并将异常显示给最终用户。
a = [1,2,3,4,5,6]try:print(a[100])except IndexError:print("索引下标出界")else:print("程序无报错")##结果索引下标出界a = [1,2,3,4,5,6]try:print(a[0])except IndexError:print("索引下标出界")else:print("程序无报错")##结果1程序无报错
4.3 处理多重异常的try……expect语句
使用带有多个expect子句的try语句结构,只要有某个expect语句捕获到了异常,则执行该expect子句下的程序代码,其他的expect子句不再进行异常的捕获。
try:<被检测的程序代码>expect <异常类型>:<异常处理的程序代码>[expect <异常类型>:<异常处理的程序代码>][expect <异常类型>:<异常处理的程序代码>][else:<正常处理的程序代码>]##[]中的内容不是必须的
例子
while True:try:x = eval(input("请输入第一个数据:"))y = int(input("请输入第二个数据:"))z = x/yexcept ValueError:print("应全部输入数值数据")except ZeroDivisionError:print("除数不能为零")except NameError:print("变量未定义")else:print("最终结果:",z)break##结果请输入第一个数据:15请输入第二个数据:a应全部输入数值数据请输入第一个数据:15请输入第二个数据:0除数不能为零请输入第一个数据:15请输入第二个数据:3最终结果: 5.0
4.4 try……expect……finally语句
无论try子句中的代码是否有异常产生,finally子句下面的程序代码都会被执行,可以用作清除异常使用。
finally必须时整个结构的最后一条语句,如果有else语句,则else语句必须出现在finally子句之前。
try:<被检测的程序代码>expect <异常类型>:<异常处理的程序代码>finally:<必定执行的程序代码>
应用:
1.在通信过程中,无论通信是否发生错误,都需要在通信完成或者发生错误的时候关闭网络连接
2.在读一个文件的时候,无论是否有异常发生,最后都要关闭文件
try:x = eval(input("请输入第一个数据:"))y = int(input("请输入第二个数据:"))z = x/yexcept ValueError:print("应全部输入数值数据")except ZeroDivisionError:print("除数不能为零")except NameError:print("变量未定义")else:print("最终结果:",z)finally:print('-----','end','-------')##结果PS C:\Users\lh> & C:/Users/lh/AppData/Local/Programs/Python/Python37/python.exe e:/pythonstduy/iter.py请输入第一个数据:15请输入第二个数据:0除数不能为零----- end -------PS C:\Users\lh> & C:/Users/lh/AppData/Local/Programs/Python/Python37/python.exe e:/pythonstduy/iter.py请输入第一个数据:15请输入第二个数据:b应全部输入数值数据----- end -------PS C:\Users\lh> & C:/Users/lh/AppData/Local/Programs/Python/Python37/python.exe e:/pythonstduy/iter.py请输入第一个数据:15请输入第二个数据:5最终结果: 3.0----- end -------
五、抛出异常
5.1 raise语句
Python使用raise语句抛出一个指定的异常。
raise唯一的一个参数指定了要被抛出的异常。它必须是一个异常的实例或异常的类(Exception的子类)
raise NameError("这里使用raise抛出了一个异常")#结果Traceback (most recent call last):File "e:/pythonstduy/iter.py", line 173, in <module>raise NameError("这里使用raise抛出了一个异常")NameError: 这里使用raise抛出了一个异常
用户也可也直接输出异常的类名称
raise IndexError()##结果Traceback (most recent call last):File "e:/pythonstduy/iter.py", line 175, in <module>raise IndexError()IndexError
class Fruit:def __init__(self,name):self.name =namedef __getattr__(self,attr): ##增加新的属性if attr != 'name':raise AttributeErrorf= Fruit("苹果")print(f.name)f.prize()##结果苹果Traceback (most recent call last):File "e:/pythonstduy/iter.py", line 187, in <module>f.prize()File "e:/pythonstduy/iter.py", line 183, in __getattr__raise AttributeErrorAttributeError
5.2 结束解释器的运行
通过输入SystemExit异常强制结束Python解释器的运行。
使用sys.exit()函数会输出一个SystemExit异常,sys.exit()函数会结束线程。
import systry:sys.exit()except SystemExit:print("目前还不能结束解释器的运行")##结果目前还不能结束解释器的运行
如果想正常结束Python解释器的运行,最好使用os模块的_exit()函数,里面必须有参数。
5.3 离开嵌套循环
在一个嵌套循环中,break语句只能离开最内层的循环,而不能离开嵌套循环,使用raise语句可以离开嵌套循环。
class ExitLoop(Exception):passtry:i = 1while i<10:for j in range(1,10):print(i,j)if (i==2) and (j==2):raise(ExitLoop)i+=1except ExitLoop:print("当i=2且j=2的时候离开嵌套循环")##结果1 12 2当i=2且j=2的时候离开嵌套循环class ExitLoop(Exception):passtry:i = 1while i<10:for j in range(0,10):print(i,j)if (i==2) and (j==2):raise(ExitLoop)i+=1except ExitLoop:print("当i=2且j=2的时候离开嵌套循环")##结果1 02 13 24 35 46 57 68 79 810 9不存在 i=2且j=2的情况
六、自定义异常
用户可以自定义异常,与内置异常的区别是内置异常是定义在exceptions模块中的。当python解释器启动的时候,exceptions模块就会事先加载。
用户也可以自定义异常类,并且用户自定义的异常类必须从一个Python的内置异常类派生而来。
一般异常类在创建的时候都以“Error”结尾,与标准异常命名一样。
class URLError(Exception):passtry:raise URLError("这是URL异常")except URLError as inst:print(inst.args[0])##结果这是URL异常#inst变量是用于自定义类URLError的实例变量,inst.args就是该用户定义异常类args属性值class MyError(Exception):def __init__(self,value):self.value =valuedef __str__(self):return repr(self,value)try:raise MyError(100)except MyError as e:print("发生异常的数值为:",e.value)##结果发生异常的数值为: 100
七、上下文管理语句
上下文管理语句with就可以实现语句块执行前的准备动作以及执行后的收尾动作。
with <上下文管理表达式> [
<语句块>
<上下文管理表达式>是支持上下文管理协议的对象,eg:file、thread、LockType、threading.Lock,负责维护上下文环境
with open('hello.txt','w') as f:f.write('hello')f.writr('Python')文件操作完成之后可以没有close()语句关闭文件,当程序完成的时候,文件会自动关闭。
八、程序调试
8.1 使用assert语句
assert <测试码> [,参数]
测试码是一段返回True或False的程序代码。如果测试码返回True,则继续运行后面的程序代码;如果测试码返回False,assert语句就会输出一个AssertionError异常,并输出assert语句的 [参数] 作为错误信息字符串。
a= 100assert(a !=0),"Error ,a =0 "a= 0assert(a !=0),"Error ,a =0 "##结果Traceback (most recent call last):File "e:/pythonstduy/iter.py", line 234, in <module>assert(a !=0),"Error ,a =0 "AssertionError: Error ,a =0try:x = int(input("x:"))y = int(input("y:"))s = "两次输入的数据不相等"assert x==y,s ##如果不相等的话,就会出现expect,抛出异常,except AssertionError:print(s)##结果x:55y:66两次输入的数据不相等PS C:\Users\lh> & C:/Users/lh/AppData/Local/Programs/Python/Python37/python.exe e:/pythonstduy/iter.pyx:55y:55
8.2 debug内置变量
Python解释器有一个内置变量debug,debug在正常情况下的值为True。
print(__debug__)##结果True
当用户以最佳化模式启动Python解释器的时候,debug的值为False。
PS C:\Users\lh> python -OPython 3.7.6 (tags/v3.7.6:43364a7ae0, Dec 19 2019, 00:42:30) [MSC v.1916 64 bit (AMD64)] on win32Type "help", "copyright", "credits" or "license" for more information.>>> __debug__False
用户是不可以设置debug的值
__debug__ = False##结果__debug__ = False^SyntaxError: assignment to keyword
debug也可以用来调试程序
if __debug__:if not (<测试码>):raise AssertionError[,参数]
例子
import typesdef checkType(arg):if __debug__:if not (type(arg)==str):raise AssertionError("参数的类型不是字符串")checkType(10)##结果Traceback (most recent call last):File "e:/pythonstduy/iter.py", line 244, in <module>checkType(10)File "e:/pythonstduy/iter.py", line 243, in checkTyperaise AssertionError("参数的类型不是字符串")AssertionError: 参数的类型不是字符串
