一.异常和错误
1.错误:错误为代码的一部分
- 语法错误:代码不符合python要求的规范;无法通过python解释器的语法检测,必须在程序执行前改正
- 逻辑错误:代码语法无误但无法实现运行;可以通过python的语法检测,程序执行时才会报错
2.异常:程序运行时发生错误的信号
二.异常种类:
- python中不同的异常可以用不同的类型表示(python中类即类型),其中包含了该类异常的信息和处理方法
- 不同类对象标识不同异常,一个异常标识一种错误
1.常用异常:
#AttributeError:试图访问一个对象没有的属性
>>> a=100
>>> a.b()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute 'b'
#IOError:输入/输出异常
#基本上是无法打开文件
#ImportError:无法引入模块或包
#基本上是路径问题或名称错误
#IndentationError:代码没有正确对齐(缩进错误,语法错误的子类)
#IndexError:下标索引超出序列边界(索引越界异常)
>>> a=[1,2,3]
>>> a[10]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
>>> a[-100]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
#KeyError:试图访问字典里不存在的键
>>> a={'name':'a'}
>>> a['age']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'age'
#KeyboardInterrupt:(程序运行时)Ctrl+C被按下(主动触发)
#NameError:使用一个未定义的变量
>>> print(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
#SyntaxError:代码非法,代码不能编译(语法错误)
>>> int a=3#实际上这是java的语法,python中不合法
File "<stdin>", line 1
int a=3
^
SyntaxError: invalid syntax
#TypeError:函数或方法接受了错误类型的参数(类型错误)
>>> sum('nick')#sum()不接受str
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'
#UnboundLocalError:试图访问一个还未被设置的局部变量
#基本上是由于另有一个同名的全局变量,导致你以为正在访问它
#ValueError:传入一个调用者不期望的值,但其类型正确(数值错误)
>>> int('nick')#'nick'str不具备表示int的含义
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'nick'
#ZeroDivisionError:除数为0的错误(零除错误)
>>> a=3/0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero
2.更多异常:
jianshu.com/p/088d36a349fb
#ArithmeticError:所有数值计算错误的基类
#AssertionError:断言语句失败
#BaseException:所有异常的基类
#BufferError:无法执行缓冲区相关操作
#DeprecationWarning:关于被弃用的特征的警告
#EnvironmentError:可在Python的系统外发生的异常的基类(操作系统错误的基类)
#EOFError:没有内建输入,到达EOF标记
#Exception:常规错误的基类
#FloatingPointError:浮点计算错误
#FutureWarning:关于构造将来语义会有改变的警告
#GeneratorExit:生成器发生异常来通知推出
#ImportWarning:关于模块进口中可能出现的错误的警告的基础类
#LookupError:无效数据查询的基类(映射/序列上使用的键/索引无效时引发的异常的基类)
#MemoryError:内存溢出错误(对python解释器不是致命的)
#NotImplementedError:尚未实现的方法
#OSError:操作系统错误
#OverflowError:数值运算超出最大限制
#OverflowWarning:python2中关于自动提升为long的警告
#PendingDeprecationWarning:关于特性将会被废弃的警告
#ReferenceError:弱引用(Weak Reference)试图访问已被垃圾回收的对象
#RuntimeError:一般的运行时错误
#RuntimeWarning:可疑的运行时行为runtime behavior的警告
#StandardError:所有的内建标准异常的基类
#StopIteration:迭代器没有更多的值
#SyntaxWarning:可疑的语法和警告
#SystemError:一般的解释器系统错误
#SystemExit:解释器请求推出
#TabError:Tab和空格混用
#UnicodeDecodeError:Unicode解码时的错误
#UnicodeEncodeError:Unicode编码时的错误
#UnicodeError:Unicode相关的错误
#UnicodeTranslateError:Unicode转换时的错误
#UnicodeWarning:与Unicode有关的警告的基类
#UserWarning:用户代码生成的警告
#VMSError:发生VMS特定错误时引发;仅适用于VMS
#Warning:警告的基类
#WindowsError:系统调用失败
3.内置异常的层次结构
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
三.异常处理:
1.概念:编写特定的代码专门用于捕捉触发的异常(这段代码与程序逻辑无关,与异常处理有关),如果捕捉成功则进入另一个处理分支,使程序不会崩溃
2.保证程序的健壮性与容错性(遇到错误时程序不会崩溃)
3.处理过程:异常也采用对象的方式处理
1.抛出异常:如果发生异常,生成该异常的一个对象,停止当前执行路径,并把异常对象提交给解释器
2.捕获异常:解释器得到该异常后,寻找相应的代码处理该异常
4.if语句:错误发生的条件可预知,在错误发生前预防
AGE=10
while True:
age=input('>>: ').strip()
if age.isdigit(): #只有在age为字符串形式的整数时,下列代码才不会出错,该条件是可预知的
age=int(age)
if age==AGE:
break
elif age.isspace():
print('输入的是空格.请重新输入')
elif leng(age)==0:
print('输入的是空,请重新输入')
else:
print('其他非法操作,请重新输入')
总结:(1)只能针对一段代码,对不同代码的相同类型错误需写重复的if(2)加入与主逻辑无关的代码使可读性变差(3)可以解决异常
5.try…except语句:错误发生的条件不可预知,在错误发生后处理
#基本语法:
try:
被检测的代码块
except 异常类型:
try中一旦检测到异常,就执行这个位置的逻辑
#举例:
try:
f=open('a.txt')
g=(line.strip() for line in f)
print(next(g))
print(next(g))
print(next(g))
print(next(g))
print(next(g))
except StopIteration:
f.close()
举例2:
AGE=10
while True:
try:
age=input('>>: ').strip()
age=int(age)
if age==AGE:
break
except ValueError as ve:
print(ve)
#input 'w'
#结果为:invalid literal for int() with base 10: 'w'
只能处理指定的异常情况;把错误处理和真正的工作分开;代码更易组织、更清晰,复杂的工作任务更易实现;更安全,不会由于一些小的疏忽而使程序意外崩溃
6.多分枝与万能异常:如果无论出现什么异常都用同一段代码逻辑去处理,则使用Exception;如果对不同异常要定制不同处理逻辑,那么需要使用多分支
#多分枝:
s1 = 'hello'
try:
int(s1)
except IndexError as e:
print(e)
except KeyError as e:
print(e)
except ValueError as e:
print(e)
#万能异常:
s1 = 'hello'
try:
int(s1)
except Exception as e:
print(e)
#多分枝后使用Exception:
s1 = 'hello'
try:
int(s1)
except IndexError as e:
print(e)
except KeyError as e:
print(e)
except ValueError as e:
print(e)
except Exception as e:
print(e)
7.else语句:当try当中代码没有触发异常时执行else中代码
8.finally语句:无论try中代码是否触发异常,都会执行finally中代码(多用于清理工作)
s1 = 'hello' / '1'
try:
int(s1)
except IndexError as e:
print(e)
except KeyError as e:
print(e)
except ValueError as e:
print(e)
except Exception as e:
print(e)
else:
print('try内代码块没有异常则执行我') #s1='hello'时不执行/s1='1'时执行
finally:
print('无论异常与否,都会执行该模块,通常是进行清理工作')
9.主动触发异常:raise 错误类型(‘传入异常类的值(默认被打印)’)
try:
raise TypeError('类型错误')
except Exception as e:
print(e)
10.自定义异常:必须继承某个父异常类
- 通常继承Exception或其子类即可
- 命名通常以Error/Exception为后缀
class EgonException(BaseException):
def __init__(self,msg):
self.msg=msg
def __str__(self): #可不添加,从BaseException继承
return self.msg
try:
raise EgonException('类型错误')
except EgonException as e:
print(e)
#结果为:类型错误
11.断言:assert条件
def test1():
pass
return 1
res1=test1()
assert res1==1 #如果断言不成立,报错,错误类型为AssertionError
#相当于:
#if res1 != 1:
# raise AssertionError
print(res1) #结果为:1
12.一般return不放到异常处理结构中,而是放到方法最后
四.何时使用:try…except与主逻辑无关,会使可读性降低,只有错误发生条件无法预知时才应加上try…except
五.追溯traceback模块:打印异常信息
1.打印异常信息到屏幕
import traceback
try:
print('step 1')
num=1/0
except:
traceback.print_exc()
#结果:
step 1
Traceback (most recent call last):
File "G:\programm\0.txt", line 6, in <module>
num=1/0
ZeroDivisionError: division by zero
2.输出异常信息到文件
import traceback
try:
print('step 1')
num=1/0
except:
with open('K:/a.txt','a') as f:
traceback.print_exc(file=f)
#结果:
step 1