我们在程序编写和运行过程中,总会遇到各种各样的错误。
1.有的错误是编写程序时语法错误。比如少了:冒号,缩进不合理等等。
2.有的错误是程序编写有问题造成的,比如本来应该输出整数结果输出了字符串,这种错误我们通常称之为bug,bug是必须修复的。
3.有的错误是用户输入造成的,比如让用户输入email地址,结果得到一个空字符串,这种错误可以通过检查用户输入来做相应的处理。
4.还有一类错误是完全无法在程序运行过程中预测的,比如写入文件的时候,磁盘满了,写不进去了,或者从网络抓取数据,网络突然断掉了。这类错误也称为异常,在程序中通常是必须处理的,否则,程序会因为各种问题终止并退出。
所以程序需要一种处理错误与异常的机制,而Python的错误异常处理能力是很强大的,它有很多内置异常,可向用户准确反馈出错信息。
1.语法错误
>>> if True print('hello world!') # 少写了:冒号
SyntaxError: invalid syntax
>>>
2.Python内置异常
异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行。
一般情况下,在Python无法正常处理程序时就会发生一个异常。
异常是Python对象,表示一个错误。
当Python脚本发生异常时我们需要捕获处理它,否则程序会终止执行。
在Python中,异常也是对象,可对它进行操作。BaseException是所有内置异常的基类,但用户定义的类并不直接继承BaseException,所有的异常类都是从Exception继承,且都在exceptions模块中定义。
Python自动将所有异常名称放在内建命名空间中,所以程序不必导入exceptions模块即可使用异常。一旦引发而且没有捕捉SystemExit异常,程序执行就会终止。如果交互式会话遇到一个未被捕捉的SystemExit异常,会话就会终止。
BaseException # 所有异常的基类
+-- SystemExit # 解释器请求退出
+-- KeyboardInterrupt # 用户中断执行(通常是输入^C)
+-- GeneratorExit # 生成器(generator)发生异常来通知退出
+-- Exception # 常规异常的基类
+-- StopIteration # 迭代器没有更多的值
+-- StopAsyncIteration # 必须通过异步迭代器对象的__anext__()方法引发以停止迭代
+-- ArithmeticError # 各种算术错误引发的内置异常的基类
| +-- FloatingPointError # 浮点计算错误
| +-- OverflowError # 数值运算结果太大无法表示
| +-- ZeroDivisionError # 除(或取模)零 (所有数据类型)
+-- AssertionError # 当assert语句失败时引发
+-- AttributeError # 属性引用或赋值失败
+-- BufferError # 无法执行与缓冲区相关的操作时引发
+-- EOFError # 当input()函数在没有读取任何数据的情况下达到文件结束条件(EOF)时引发
+-- ImportError # 导入模块/对象失败
| +-- ModuleNotFoundError # 无法找到模块或在在sys.modules中找到None
+-- LookupError # 映射或序列上使用的键或索引无效时引发的异常的基类
| +-- IndexError # 序列中没有此索引(index)
| +-- KeyError # 映射中没有这个键
+-- MemoryError # 内存溢出错误(对于Python 解释器不是致命的)
+-- NameError # 未声明/初始化对象 (没有属性)
| +-- UnboundLocalError # 访问未初始化的本地变量
+-- OSError # 操作系统错误,EnvironmentError,IOError,WindowsError,socket.error,select.error和mmap.error已合并到OSError中,构造函数可能返回子类
| +-- BlockingIOError # 操作将阻塞对象(e.g. socket)设置为非阻塞操作
| +-- ChildProcessError # 在子进程上的操作失败
| +-- ConnectionError # 与连接相关的异常的基类
| | +-- BrokenPipeError # 另一端关闭时尝试写入管道或试图在已关闭写入的套接字上写入
| | +-- ConnectionAbortedError # 连接尝试被对等方中止
| | +-- ConnectionRefusedError # 连接尝试被对等方拒绝
| | +-- ConnectionResetError # 连接由对等方重置
| +-- FileExistsError # 创建已存在的文件或目录
| +-- FileNotFoundError # 请求不存在的文件或目录
| +-- InterruptedError # 系统调用被输入信号中断
| +-- IsADirectoryError # 在目录上请求文件操作(例如 os.remove())
| +-- NotADirectoryError # 在不是目录的事物上请求目录操作(例如 os.listdir())
| +-- PermissionError # 尝试在没有足够访问权限的情况下运行操作
| +-- ProcessLookupError # 给定进程不存在
| +-- TimeoutError # 系统函数在系统级别超时
+-- ReferenceError # weakref.proxy()函数创建的弱引用试图访问已经垃圾回收了的对象
+-- RuntimeError # 在检测到不属于任何其他类别的错误时触发
| +-- NotImplementedError # 在用户定义的基类中,抽象方法要求派生类重写该方法或者正在开发的类指示仍然需要添加实际实现
| +-- RecursionError # 解释器检测到超出最大递归深度
+-- SyntaxError # Python 语法错误
| +-- 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/except
try:
try_suite #要处理的逻辑代码
except Exception[e]: #Exception是要处理的异常类,e用于保存出现异常的类型
exception_block #处理捕获异常之后的逻辑
#try用来捕获try_suite中的操作,并且将错误交给except处理。
#except用来处理异常,如果处理异常和设置异常一致,使用exception_block处理异常,不一致的话就会被解释器处理,如果有e设置时,这个错误就会保存在e中。
如下代码:
try:
a
except NameError as e:
print('Error:',e)
print 'over'
#输出结果
Error: name 'a' is not defined
over
如下异常可以捕获,因为是运行时错误:
try:
undef
except:
print("catch an except")
不能捕获异常,因为是语法错误,运行前错误(因为代码运行前解释器会对语法进行检查,有错误就抛出,这时代码还没有真正运行)
>>> try:
if undef
except:
print("catch an except")
SyntaxError: invalid syntax
>>>
如下异常可以捕获,可以指定处理某种异常(NameError):
>>> try:
undef
except NameError as e:
print('catch an except {}'.format(e))
catch an except name 'undef' is not defined
>>>
如下代码:
输出结果,报错,错误是NameError: name 'undef' is not defined
不能捕获异常,因为设置IOError,不会处理NameError,会把异常抛给解释器进行处理
>>> try:
undef
except IOError as e:
print('catch an except {}'.format(e))
Traceback (most recent call last):
File "<pyshell#41>", line 2, in <module>
undef
NameError: name 'undef' is not defined
>>>
try/except...else
else 子句将在 try 子句没有发生任何异常的时候执行。
>>> try:
print(name)
except Exception as e: #所有的异常都处理
print('error come: {}'.format(e))
else:
print('no error') #try 子句发生任何异常,不执行这里
error come: name 'name' is not defined
>>> try:
name='James'
print(name)
except Exception as e:
print('error come: {}'.format(e))
else:
print('no error') #try 子句没有发生任何异常,执行这里
James
no error
>>>
try-finally
finally 语句无论是否发生异常都将执行最后的代码。
>>> try:
print(name)
except Exception as e:
print('error come: {}'.format(e))
else:
print('no error')
finally:
print('finally come here') #无论是否发生异常都将执行最后的代码
error come: name 'name' is not defined
finally come here
>>>
抛出异常
Python 使用 raise 语句抛出一个指定的异常。
raise语法格式如下:
raise [Exception [, args [, traceback]]]
以下实例如果 x 大于 5 就触发异常:
>>> x=6
>>> if x>5:
raise Exception('x cannot large than 5, x={}'.format(x))
Traceback (most recent call last):
File "<pyshell#4>", line 2, in <module>
raise Exception('x cannot large than 5, x={}'.format(x))
Exception: x cannot large than 5, x=6
>>>