【Python】解析Python中的异常操作
目录结构:
python中的异常分为运行时异常和语法异常,运行时异常发生在程序运行阶段,而语法异常发生在解释器检查阶段。该文章接下来所提到的异常都是运行时异常。
1.try,except,else,finally块
下面是python中与异常相关的关键字
关键字 | 关键字说明 |
try/except | 捕获异常说明 |
else | 如果try没有捕获到异常,则执行else的语句 |
finally | 无论是否出现异常,都执行代码 |
下面将逐步讲解这些关键字的使用。
1.1 异常处理
捕捉异常可以使用try/except语句。
try/except语句用来检测try语句块中的错误,从而让except语句捕获异常信息并处理。
如果你不想在异常发生时结束你的程序,只需在try里捕获它。
打开一个文件,在该文件中的内容写入内容
try: fh = open("testfile", "w") fh.write("这是一个测试文件,用于测试异常!!") except IOError: print "Error: 没有找到文件或读取文件失败" else: print "内容写入文件成功" finally: fh.close()
1.2 使用except而不带任何异常类型
你可以不带任何异常类型使用except,如下实例:
try: 正常的操作 ...................... except: 发生异常,执行这块代码 ...................... else: 如果没有异常执行这块代码
以上方式try-except语句捕获所有发生的异常。我们可以使用sys.exc_info()自己捕获异常详细信息,exc_info()的返回值是一个包含三个元素的Tuple(元组)数据类型。格式为(type, value, traceback),其中type是被捕获异常的类型(BaseException的派生类),value是异常实例(异常类型的实例),traceback是一个traceback对象(包含了异常抛出后的方法调用栈信息)
例如:
import traceback import sys try: raise ValueError('this is a exp') except: ex_type, ex_val, ex_stack = sys.exc_info() print(ex_type) print(ex_val) for stack in traceback.extract_tb(ex_stack): print(stack)
1.3 使用except而带多种异常类型
try: 正常的操作 ...................... except(Exception1[, Exception2[,...ExceptionN]]]): 发生以上多个异常中的一个,执行这块代码 ...................... else: 如果没有异常执行这块代码
案例:
try: f1 = open("testfile.txt", "w+") f1.read() a = 1 / 0 except (IOError,ZeroDivisionError) as ercode: print("发生错误了,错误代码为:" + str(ercode)) else: print("内容写入文件成功") f1.close()
1.4 try-finally 语句
try-finally 语句无论是否发生异常都将执行最后的代码。
try: <语句> finally: <语句> #退出try时总会执行 raise
下面案例从代码上保证了程序的健壮性:
try: fh = open("testfile", "w") try: fh.write("这是一个测试文件,用于测试异常!!") finally: print "关闭文件" fh.close() except IOError: print "Error: 没有找到文件或读取文件失败"
2.内置的异常类
下面的表列举了部分标准的python异常
异常名称 | 描述 |
AssertionError | 断言语句(assert)失败 |
AttributeError | 尝试访问未知的对象属性 |
EOFError | 用户输入文件末尾标志EOF(Ctrl+d) |
FloatingPointError | 浮点计算错误 |
GeneratorExit | generator.close()方法被调用的时候 |
ImportError | 导入模块失败的时候 |
IndexError | 索引超出序列的范围 |
KeyError | 字典中查找一个不存在的关键字 |
KeyboardInterrupt | 用户输入中断键(Ctrl+c) |
MemoryError | 内存溢出(可通过删除对象释放内存) |
NameError | 尝试访问一个不存在的变量 |
NotImplementedError | 尚未实现的方法 |
OSError | 操作系统产生的异常(例如打开一个不存在的文件) |
OverflowError | 数值运算超出最大限制 |
ReferenceError | 弱引用(weak reference)试图访问一个已经被垃圾回收机制回收了的对象 |
RuntimeError | 一般的运行时错误 |
StopIteration | 迭代器没有更多的值 |
SyntaxError | Python的语法错误 |
IndentationError | 缩进错误 |
TabError | Tab和空格混合使用 |
SystemError | Python编译器系统错误 |
SystemExit | Python编译器进程被关闭 |
TypeError | 不同类型间的无效操作 |
UnboundLocalError | 访问一个未初始化的本地变量(NameError的子类) |
UnicodeError | Unicode相关的错误(ValueError的子类) |
UnicodeEncodeError | Unicode编码时的错误(UnicodeError的子类) |
UnicodeDecodeError | Unicode解码时的错误(UnicodeError的子类) |
UnicodeTranslateError | Unicode转换时的错误(UnicodeError的子类) |
ValueError | 传入无效的参数 |
ZeroDivisionError | 除数为零 |
python异常类的层次结构
BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
+-- StopIteration
+-- ArithmeticError
| +-- FloatingPointError
| +-- OverflowError
| +-- ZeroDivisionError
+-- AssertionError
+-- AttributeError
+-- BufferError
+-- EOFError
+-- ImportError
+-- LookupError
| +-- IndexError
| +-- KeyError
+-- MemoryError
+-- NameError
| +-- UnboundLocalError
+-- OSError
| +-- BlockingIOError
| +-- ChildProcessError
| +-- ConnectionError
| | +-- BrokenPipeError
| | +-- ConnectionAbortedError
| | +-- ConnectionRefusedError
| | +-- ConnectionResetError
| +-- FileExistsError
| +-- FileNotFoundError
| +-- InterruptedError
| +-- IsADirectoryError
| +-- NotADirectoryError
| +-- PermissionError
| +-- ProcessLookupError
| +-- TimeoutError
+-- ReferenceError
+-- RuntimeError
| +-- NotImplementedError
+-- SyntaxError
| +-- IndentationError
| +-- TabError
+-- SystemError
+-- TypeError
+-- ValueError
| +-- UnicodeError
| +-- UnicodeDecodeError
| +-- UnicodeEncodeError
| +-- UnicodeTranslateError
+-- Warning
+-- DeprecationWarning
+-- PendingDeprecationWarning
+-- RuntimeWarning
+-- SyntaxWarning
+-- UserWarning
+-- FutureWarning
+-- ImportWarning
+-- UnicodeWarning
+-- BytesWarning
+-- ResourceWarning
3.自定义异常类
下面的这张图片是python中的异常继承树
python的异常有个大基类BaseException。然后继承的是Exception。所以我们自定义类也必须继承Exception。
#最简单的自定义异常 class FError(Exception): pass
抛出异常、用try-except抛出
try: raise FError("自定义异常") except FError as e: print(e)
下面的异常类模板比较常见
class CustomError(Exception): def __init__(self,ErrorInfo): super().__init__(self) #初始化父类 self.errorinfo=ErrorInfo def __str__(self): return self.errorinfo if __name__ == '__main__': try: raise CustomError('客户异常') except CustomError as e: print(e)
4.如何抛出异常
当程序出现错误,python会自动引发异常,也可以通过raise显示地引发异常。一旦执行了raise语句,raise后面的语句将不能执行。
我们可以使用raise语句自己触发异常
raise语法格式如下:
raise [Exception [, args [, traceback]]]
语句中 Exception 是异常的类型(例如,NameError)参数标准异常中任一种,args 是自已提供的异常参数。
最后一个参数是可选的(在实践中很少使用),如果存在,是跟踪异常对象。
实例
一个异常可以是一个字符串,类或对象。 Python的内核提供的异常,大多数都是实例化的类,这是一个类的实例的参数。
定义一个异常非常简单,如下所示:
def functionName( level ): if level < 1: raise Exception("Invalid level!", level) # 触发异常后,后面的代码就不会再执行
注意:为了能够捕获异常,"except"语句必须有用相同的异常来抛出类对象或者字符串。
例如我们捕获以上异常,"except"语句如下所示:
try: 正常逻辑 except Exception,err: 触发自定义异常 else: 其余代码
实例:
#!/usr/bin/python # -*- coding: UTF-8 -*- # 定义函数 def mye( level ): if level < 1: raise Exception,"Invalid level!" # 触发异常后,后面的代码就不会再执行 try: mye(0) # 触发异常 except Exception,err: print 1,err else: print 2
执行以上代码,输出结果为:
$ python test.py
1 Invalid level!
python3.6以后 改为
def mye( level ): if level < 1: raise Exception("Invalid level!") # 触发异常后,后面的代码就不会再执行 try: mye(0) # 触发异常 except Exception as err: print(1,err) else: print(2)
5.设置断言语句
python支持assert语句,assert的用法如下:
assert condition
如果condition为false,那么raise一个AssertionError出来。逻辑上等同于:
if not condition: raise AssertionError()
也可以为assert添加异常参数
assert expression [, arguments] assert 表达式 [, 参数]
案例:
import sys assert ('linux' in sys.platform), "This code runs on Linux only."
参考文章:
https://www.runoob.com/python/python-exceptions.html
https://blog.csdn.net/qq_39247153/article/details/81082313
https://www.geeksforgeeks.org/python-set-5-exception-handling/