一、异常和错误
python中有两种错误:
1、语法错误(过不了解释器的语法检测,必须在程序执行前改正。)
2、 逻辑错误,解释器的语法检测不到,执行后可能会出现异常,但这个异常时可以捕获的。
注意:异常发生后,异常之后的代码就不执行了
python中的异常种类
常见的异常种类:
AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
IOError 输入/输出异常;基本上是无法打开文件
ImportError 无法引入模块或包;基本上是路径问题或名称错误
IndentationError 语法错误(的子类) ;代码没有正确对齐
IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
KeyError 试图访问字典里不存在的键
KeyboardInterrupt Ctrl+C被按下
NameError 使用一个还未被赋予对象的变量
SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
TypeError 传入对象类型与要求的不符合
UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,
导致你以为正在访问它
ValueError 传入一个调用者不期望的值,即使值的类型是正确的
二、异常处理: try-except语句
语法结构如下:
try:
检测范围
except Exception[as reason]:
出现异常(Exception)后处理的代码
举个例子来说明一下 try-except是怎么使用的
f = open('我是一个不存在的文档.txt') # 文件不存在将会报错
print(f.read())
f.close()
# output
Traceback (most recent call last):
File "C:/python文件都在这里/python 全栈/day9-21/day21/2.异常处理.py", line 2, in <module>
f = open('我是一个不存在的文档.txt')
FileNotFoundError: [Errno 2] No such file or directory: '我是一个不存在的文档.txt'
修改为:
try:
f = open('我是一个不存在的文档.txt')
print(f.read())
f.close()
except OSError:
print('文件打开的过程中出错啦!')
# output
文件打开的过程中出错啦!
但是从程序员的角度上来说,导致OSError异常的原因有很多(如 FileExistsError、FileNotFoundError、PermissionError等),所以可能会更在意错误的具体内容,这里可以使用as把具体的错误信息给打印出来。
...
except OSError as reason:
print('文件打开的过程中出错啦!\n错误原因是:', str(reason))
- 针对不同异常设置多个except
一个try语句可以和多个except搭配,分别对感兴趣的异常进行检测处理。
try:
sum = 7 + '7' # 注意:该异常语句下面的语句将不会再执行
f = open('我是一个不存在的文档.txt')
print(f.read())
f.close()
except OSError as reason:
print('文件打开的过程中出错啦!\n错误原因是:', str(reason))
except TypeError as reason:
print('类型出错啦!\n错误原因是:', str(reason))
# output
类型出错啦!
错误原因是: unsupported operand type(s) for +: 'int' and 'str'
- 对多个异常做统一处理
try:
sum = 7 + '7'
f = open('我是一个不存在的文档.txt')
print(f.read())
f.close()
except (OSError, TypeError) as reason:
print('出错啦!\n错误原因是:', str(reason))
# output
出错啦!
错误原因是: unsupported operand type(s) for +: 'int' and 'str'
try:
sum = 7 + '7'
f = open('我是一个不存在的文档.txt')
print(f.read())
f.close()
except TypeError as reason:
print('出错啦!\n错误原因是:', str(reason))
except OSError as reason:
print('出错啦!\n错误原因是:', str(reason))
# output
出错啦!
错误原因是: unsupported operand type(s) for +: 'int' and 'str'
- 捕获所有异常
不过通常不建议这么做,因为它会隐藏程序员未想好并未做好准备处理的错误,例如,当用户通过Ctrl + C快捷键强制终止程序,却会被解释为:KeyboardInterrupt异常。
...
except:
print('出错啦!')
...
...
except Exception as reason:
print(reason)
...
三、异常处理: try-finally语句
如果在一些场合,就算出现了异常,也不得不执行收尾工作(例如在程序崩溃前保存用户文档),引入了finally来拓展try。
try:
f = open('我是一个不存在的文档.txt')
print(f.read())
sum = 7 + '7'
except:
print('出错啦!')
finally:
# f.close() # 哭,加了这一句报错f没有定义
print('嘻嘻,别担心,程序停止前我瞧瞧关闭了文件~~')
finally语句块中的内容就是确保无论如何都将被执行的内容。
raise 语句
raise语句用于主动触发异常
>>> raise ZeroDivisionError
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError
抛出的异常还可以带参数,表示异常的解释
>>> raise ZeroDivisionError('除数不能为0!!')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: 除数不能为0!!
四、自定义异常
class EvaException(BaseException):
def __init__(self,msg):
self.msg=msg
def __str__(self):
return self.msg
try:
raise EvaException('类型错误')
except EvaException as reason:
print(reason)
五、异常的继承关系
BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
+-- StopIteration
+-- StandardError
| +-- BufferError
| +-- ArithmeticError
| | +-- FloatingPointError
| | +-- OverflowError
| | +-- ZeroDivisionError
| +-- AssertionError
| +-- AttributeError
| +-- EnvironmentError
| | +-- IOError
| | +-- OSError
| | +-- WindowsError (Windows)
| | +-- VMSError (VMS)
| +-- EOFError
| +-- ImportError
| +-- LookupError
| | +-- IndexError
| | +-- KeyError
| +-- MemoryError
| +-- NameError
| | +-- UnboundLocalError
| +-- ReferenceError
| +-- RuntimeError
| | +-- NotImplementedError
| +-- SyntaxError
| | +-- IndentationError
| | +-- TabError
| +-- SystemError
| +-- TypeError
| +-- ValueError
| +-- UnicodeError
| +-- UnicodeDecodeError
| +-- UnicodeEncodeError
| +-- UnicodeTranslateError
+-- Warning
+-- DeprecationWarning
+-- PendingDeprecationWarning
+-- RuntimeWarning
+-- SyntaxWarning
+-- UserWarning
+-- FutureWarning
+-- ImportWarning
+-- UnicodeWarning
+-- BytesWarning
异常的继承关系
六、番外:丰富的else语句
1. 要么怎么,要么不怎样
if 条件:
条件为真执行
else:
条件为假执行
2. 干完了能怎样,干不完就别想怎样
else可以和 for 和 while 循环语句配合使用,但else语句块只在循环完成后执行,也就是说,如果循环中间使用break 语句跳出循环,那么else里边的内容就不会被执行了。
def show_max_factor(num):
count = num // 2
while count > 1:
if num % count == 0:
print('%d的最大公约数是%d' % (num, count))
break
count -= 1
else:
print('%d 是素数!' % num)
3. 没有问题?那就干吧
else 语句和异常处理搭配:只要try 语句块里没有出现任何异常,那么就是执行else语句块的内容。
try:
int('jacky')
except ValueError as reason:
print('出错啦!' + str(reason))
else:
print('没有任何异常!')