1、什么是异常
在实际工作中,我们遇到的情况不可能是非常完美的。比如:你写的某个模块,用户输入不一定符合你的要求;你的程序要打开某个文件,这个文件可能不存在或者文件格式不对;你要读取数据库的数据,数据可能是空的;我们的程序再运行着,但是内存或硬盘可能满了等等。
软件程序在运行过程中,非常可能遇到网刚刚提到的这些问题,我们称之为异常,英文是Exception, 意思是例外。遇到这些例外情况,或者异常,我们怎么让写的程序做出合理的处理,而不至于程序崩溃呢?异常机制本质:
异常指程序运行过程中出现的非正常现象,例如用户输入错误、除数为零、需要处理的文件不存在、数组下标越界等。
所谓异常处理,就是指程序在出现问题时依然可以正确的执行剩余的程序,而不会因为异常而终止程序执行。
2、异常处理举例
如果我们要拷贝一个文件,在没有异常机制的情况下,我们需要考虑各种异常情况。
伪代码如下:这样做就会很麻烦。
这种方式,有两个坏处:
1.逻辑代码和错误处理代码放一起!
2.程序员本身需要考虑的例外情况较复杂,对程序员本身要求较高!(要写很多种可能出现的情况)如果是使用python的异常机制来处理,示意代码就可能如下:
# 将d:/a.txt拷贝到e盘 try: #try 里放可能出问题的代码copyFile("d:/a.txt", "e:/a.txt") # 核心代码 except:print("文件无法拷贝“)
3、异常类
在Python编程中,有很多很多用来描述和处理异常的类,称为异常类。异常类定义中包含了该类异常的信息和对异常进行处理的方法。
Python中内建异常类的继承层次:
可以先只关注Exception中的,其余的先不管。
4、处理过程 (try…… except结构)
遇到异常一定要自己去查!!!!希望下面一个文章是自己记录的,遇到的30个错误!python中一切都是对象,异常也采用对象的方式来处理。处理过程:
1.抛出异常:在执行一个方法时,如果发生异常,则这个方法生成代表该异常的一个对象,停止当前执行路径,并把异常对象提交给解释器。
2.捕获异常:解释器得到该异常后,寻找相应的代码来处理该异常。1、try …… except……结构:
try:被监控的可能引发异常的语句块 except BaseException [as e]:异常处理语句块
try块包含着可能引发异常的代码,except块则用来捕捉和处理发生的异常。执行的时
候,如果try块中没有引发异常,则跳过ecept块继续执行后续代码:执行的时候,如果try
块中发生了异常,则跳过try块中的后续代码,跳到相应的except块中处理异常;异常处理
完后,继续执行后续代码。例如:
try:print ("step1")a=3/0print ("step2") except BaseException as e:print ("step3")print (e)print ("step4")
这段代码的输出结果是:
step1
step3
division by zero
step4
在这段代码中,我们使用了`try-except`代码块来处理异常。当执行到`a=3/0`时,会抛出一个`ZeroDivisionError`异常,因为除数为零。
由于我们已经在`try`块中处理了这个异常,程序会跳过`print("step2")`语句,而是执行`except`块中的代码。在这个例子中,我们只是简单地打印了异常消息,然后程序继续运行。
最后,程序输出了`step4`,结束了整个程序的执行。
总之,当Python解释器执行到一个异常时,它会停止当前正在执行的代码块,并且会查找`try`块中是否有对应的`except`块。如果有,则执行该`except`块中的代码。如果没有,则将异常向上传递,直到找到一个能够处理该异常的代码块为止。
这其中的e:
`as e`是用来给捕获到的异常指定一个名称,以便在`except`块中访问该异常对象。具体来说,`except BaseException as e:`中的`as e`部分是将捕获到的异常对象赋值给变量`e`。这样做的好处是我们可以在`except`块中访问这个异常对象,并对它进行进一步的处理,比如打印异常信息、记录日志等操作。
如果我们打印`e`,就会输出异常的详细信息,包括异常类型和异常消息。例如,在这段代码中,`print(e)`的输出结果是`division by zero`,表明发生了除以零的错误。你也可以使用这个异常对象调用其他方法,比如`e.args`来获取异常的参数信息。
在这个例子中,由于执行了`a=3/0`这行代码,会引发一个`ZeroDivisionError`异常。在`except`块中的`as e`语句将这个异常对象赋值给变量`e`。
2、try ……多个 except……结构:
从经典理论考虑,一般建议尽量捕获可能出现的多个异常(按照先子类再父类的顺序),并且针对性的写出异常处理代码,通常为了避免遗漏,可以在最后增加BaseException。
通常Exeption1是Exception2的子类,或者两者同级。
结构:
try:被监控的、可能引发异常的语句块except Exception1:处理Exception1的语句块 except Exception2:处理Exception2的语句块 …except BaseException1:处理可能遗漏的异常的语句块
3、try …… except……else结构:
如果try模块中没有抛出异常,则执行else模块,出现异常则执行except模块。
4、try …… except……finally结构:
try…except...finally结构中,finally块无论是否发生异常都会被执行,通常用来释放try块中
申请的资源。
5、Return语句和异常处理问题
我们一般不把return放到异常处理结构中,而是放到方法最后!
6、常见异常的解决
`ValueError`、`Exception`和`StopIteration`是异常类(Exception class)的名称,用于处理不同类型的异常情况。
1. ValueError:数值错误(数型错误)
`ValueError`是Python内置的一个异常类,用于表示数值相关的错误。当函数或操作接收到一个无效的数值参数时,就会引发`ValueError`异常。例如,当尝试将一个非数字字符串转换为数字时,会引发`ValueError`。可以使用`try`和`except`语句捕获和处理`ValueError`异常:
try:num = int(input("请输入一个整数:")) except ValueError:print("输入的不是有效的整数!")
在这段代码中:
1. `try`语句块内包含可能会引发异常的代码,这里尝试将用户输入的内容转换为整数。
2. 如果`int(input("请输入一个整数:"))`这行代码执行时抛出了`ValueError`异常(例如用户输入了一个非整数字符串),那么程序会立即跳转到对应的`except`语句块。
3. `except ValueError:`指定了要捕获的异常类型为`ValueError`,当捕获到这个异常时,会执行`print("输入的不是有效的整数!")`语句。
4. 如果没有发生异常,`except`语句块将被跳过,程序继续向下执行。通过使用`try`和`except`语句,可以在程序执行过程中检测和处理异常情况,从而使程序更加健壮和稳定。
2. Exception:
`Exception`是所有内置异常类的基类,它是一个通用的异常类。如果一个异常没有特定的异常类与之对应,那么它将被视为`Exception`的子类。因此,可以使用`Exception`类来捕获和处理大多数异常情况。在编写异常处理代码时,一般会将`Exception`放在最后,以确保能够捕获所有未处理的异常。
以下是一个简单的示例,演示如何使用自定义异常类和`try`、`except`语句处理异常:
# 定义一个自定义异常类 class MyCustomException(Exception):def __init__(self, value):self.value = valuedef __str__(self):return f"Custom Exception: {self.value}" # 函数示例:除法运算,可能会引发异常 def division(a, b):if b == 0:raise MyCustomException("除数不能为零!")return a / b # 主程序 try:result = division(10, 0) except MyCustomException as e:print(f"捕获到自定义异常:{e}") else:print(f"结果为:{result}")
在这段代码中:
1. 我们首先定义了一个自定义异常类`MyCustomException`,它继承自内置的`Exception`类,并包含了自定义的异常描述信息。
2. `division`函数用于执行除法运算,如果除数为零,则会通过`raise`关键字抛出自定义异常`MyCustomException`。
3. 在主程序中,我们使用`try`、`except`语句块捕获可能出现的异常。如果发生了自定义异常,则会执行`except MyCustomException as e:`下的代码块,打印出自定义异常的描述信息。
4. 如果没有发生异常,则会执行`else:`下的代码块,打印出计算结果。通过自定义异常类和`try`、`except`语句,我们可以更好地控制程序的异常情况,并根据需要进行异常处理。
3. `StopIteration`:
`StopIteration`是一个内置异常类,通常用于迭代器(iterator)的控制流程。当迭代器没有更多元素可供迭代时,就会引发`StopIteration`异常。这个异常类在循环遍历迭代器时特别有用,它可以帮助我们判断何时结束循环。
需要注意的是,异常是在运行时检测到的错误或异常情况,并且可以通过编写异常处理代码来进行捕获和处理,以便在出现异常时采取适当的操作。
4. SyntaxRrror: 语法错误
int a = 3 # SyntaxError :invalid syntax
(正确的是 a = 3,python中不需要显式地指定变量类型)
5. NameError:尝试访问一个没有声明的变量
print(a) # NameError: name’a' is not defined
6. ZeroDisionError:division by zero
a = 3/0
ZeroDivisionError:divison by zero
7.TypeError:类型错误
123 + "abc"
TypeError:unsupported operand type(s) for +: 'int' and 'str'8.AttributeError:访问对象的不存在的属性
a = 100
a.sayhi()
AttributeError:'int' object has no attribute 'sayhi'
这个错误消息表明在整数对象上尝试访问一个不存在的属性或方法(例如 "sayhi")导致了 AttributeError 错误。
9. indexError :索引越界异常
a = [4,5,6]
a [10]
indexError:list index index out of range
10. KeyError:字典的关键字不存在
a = {'name': 'hhh', 'age':18}
a['abc']
KeyError :'salary'
7、自定义异常类
程序开发中,有时候我们也需要自己定义异常类。自定义异常类一般都是运行时异常,通常继承Exception戌其子类即可。命名一般以Error、Exception为后缀:
自定义异常由raise语句主动抛出。# 测试自定义异常类 class AgeError(Exception):# 继承Exception类# 规定年龄在某区间为正常,其余为异常def __init__(self,errorInfo):Exception.__init__(self)self.errorInfo = errorInfodef __str__(self):return str(self.errorInfo)+ ",年龄应该在1-150岁之间"# 测试代码 if __name__ == "__main__":# 如果为True,则模块是作为独立文件运行,可以执行测试代码age = int(input("请输出一个年龄:"))if age < 1 or age > 150:raise AgeError(f"{age}是错误的年龄")else:print("年龄正常")