处理异常(Exception)

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/0
    print ("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 = value
    def __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 = errorInfo
        
    def __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("年龄正常")

​​​​​​​

  • 18
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wmpreturn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值