Python3之错误和异常

本文详细介绍了Python3中的错误和异常处理,包括语法错误和逻辑错误的区别,异常的概念,以及异常处理的常用方法:try/except、try/except...else、try-finally语句,并讲解了如何抛出异常、用户自定义异常以及预定义的清理行为,例如with语句的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、错误(error)

python中的错误一般分为语法错误和逻辑错误,分别为:

语法错误:代码不符合解释器或者编译器语法,如for循环体缺少冒号:等
逻辑错误:不完整或不合法输入或计算出现问题,如0作为除数等

二、异常(Exception)

程序运行期间检测到的错误被称为异常,大多数的异常都不会被程序处理,而是以错误信息的形式抛出

三、异常处理

1、try/except

异常的捕获可以使用try/except语句,具体语法为:

try:
    语句A
except:
    语句B

try/except的执行逻辑为:

  • 首先执行try子句,即语句A
  • 如果语句A没有遇到异常,则语句A执行完成后结束,忽略except子句,即语句B
  • 如果执行语句A的过程中发生了异常,语句A后续剩余的代码被忽略;如果异常的类型和except的名称相符,则对应的except子句将被执行;如果遇到的异常与所有的except语句均不匹配,异常将传递到上层的try中

注意:

  • 一个try语句可以包含多个except语句,分别用来处理不同的异常,但最多只有一个except语句被执行
  • 一个except语句可以处理多个异常,这些异常作为一个元组放在一个括号内,如:
except (RuntimeError, TypeError, NameError):
    语句A
  • 最后一个except子句可以忽略异常的名称,它将被当作通配符使用。可以使用这种方法打印一个错误信息,然后再次把异常抛出;
import sys
def ReadFile(path):
    try:
        file = open(path)
        strA = file.readline()
        print("文件内容为:" , strA)
    except OSError as error:
        print("OS error: {0}".format(error))
    except UnicodeDecodeError as UDR:
        print("UnicodeDecodeError: {0}".format(UDR))
    except:
        print("Unexpected error:", sys.exc_info()[0])
        raise

ReadFile("./ErrorFile.txt")
UnicodeDecodeError: 'gbk' codec can't decode byte 0x80 in position 8: illegal multibyte sequence

2、try/except...else语句

try/except语句可以增加一个else子句,else子句必须放在所有的except子句之后,else子句将在try子句没有发生异常时执行。try/except...else语法为:

try:
    语句A
except:
    语句B
else:
    语句C
# 2、try/except...else语句
import sys
def ReadFile(path):
    try:
        file = open(path , "r" , encoding='UTF-8')
    except OSError as error:
        print("OS error: {0}".format(error))
    else:
        listA = file.readlines()
        print("文件内容为:")
        for line in listA:
            print(line.strip())

ReadFile("./ErrorFile.txt")
文件内容为:
这是一个错误
Python是最好的语句

注:异常处理不仅能捕获发生在try子句中的异常,还能捕获try子句函数调用时抛出的异常

# 3、异常处理不仅能捕获发生在try子句中的异常,还能捕获try子句函数调用时抛出的异常
def func():
    return 1/0
try:
    func()
except ZeroDivisionError as err:
    print("ZeroDivisionError:" , err)
ZeroDivisionError: division by zero

 3、try - finally语句

try - finally语句中的finally语句无论异常是否出现,均会被执行

try - finally语句语法:

try:
    try语句代码块
except:
    发生异常时执行except语句代码块
else:
    没有发生异常时执行else语句代码块
finally:
    有没有异常都会执行finally代码块
# 4、try-finally 语句
import sys
def ReadFile(path):
    try:
        file = open(path)
        #如果open()语法发生异常,print()将不会被执行
        print("try语句被执行")
    except FileNotFoundError as fnf_error:
        print(fnf_error)
        print("except语句被执行")
    else:
        try:
            read_data = file.read()
        except UnicodeDecodeError as UDE_error:
            print("UDE_error:{0}".format(UDE_error))
        print("else语句被执行")
    finally:
        print('finally语句无论是否发生异常都会执行~')

ReadFile("./ErrorFile.txt")
print("----分割线----")
ReadFile("./file.txt")
try语句被执行
UDE_error:'gbk' codec can't decode byte 0x80 in position 8: illegal multibyte sequence
else语句被执行
finally语句无论是否发生异常都会执行~
----分割线----
[Errno 2] No such file or directory: './file.txt'
except语句被执行
finally语句无论是否发生异常都会执行~

4、抛出异常

Python使用raise语句抛出指定的异常,语法为:

raise Exception(args , traceback)

# 5、raise抛出异常
for i in range(20):
    if i <= 10:
        if i %2 == 0:
            print(i , '是偶数')
        else:
            print(i , '不是偶数')
    else:
        raise Exception('raise抛出异常:不能大于等于 11 ,i 的值为: {}'.format(i))
Traceback (most recent call last):
  File "G:/Python/Runoob/ZX_19_错误和异常/1.py", line 9, in <module>
    raise Exception('raise抛出异常:不能大于等于 11 ,i 的值为: {}'.format(i))
Exception: raise抛出异常:不能大于等于 11 ,i 的值为: 11
0 是偶数
1 不是偶数
2 是偶数
3 不是偶数
4 是偶数
5 不是偶数
6 是偶数
7 不是偶数
8 是偶数
9 不是偶数
10 是偶数

 raise 唯一的参数指定了要被抛出的异常,它必须是一个异常的实例或是异常的类(也就是 Exception 的子类)

raise语句可以仅抛出异常,而不去处理这个异常,如:

try:
    raise NameError('自定义NameError异常')
except NameError:
    print('抛出自定义NameError异常')
    raise
抛出自定义NameError异常
Traceback (most recent call last):
  File "G:/Python/Runoob/ZX_19_错误和异常/1.py", line 2, in <module>
    raise NameError('自定义NameError异常')
NameError: 自定义NameError异常

5、用户自定义异常

用户可以通过创建一个新的异常类来定义用户自己的异常,新创建的异常类需继承Exception类,可以是直接继承,也可以是间接继承

# 6、用户自定义异常
class MyError(Exception):
    def __init__(self, value):
        self.value = value

    def __str__(self):
        return repr(self.value)

try:
    raise MyError(2*2)
except MyError as e:
    print('My exception occurred, value:', e.value)

raise MyError('用户自定义异常')
Traceback (most recent call last):
  File "G:/Python/Runoob/ZX_19_错误和异常/1.py", line 14, in <module>
    raise MyError('用户自定义异常')
__main__.MyError: '用户自定义异常'
My exception occurred, value: 4

当一个模块有可能抛出多种不同的异常时,通常做法是为这个模块建立一个基础异常类,基于这个基础异常类为不同的错误场景创建不同的异常子类

class Error(Exception):
    """Base class for exceptions in this module."""
    pass
 
class InputError(Error):
    """Exception raised for errors in the input.
 
    Attributes:
        expression -- input expression in which the error occurred
        message -- explanation of the error
    """
 
    def __init__(self, expression, message):
        self.expression = expression
        self.message = message
 
class TransitionError(Error):
    """Raised when an operation attempts a state transition that's not
    allowed.
 
    Attributes:
        previous -- state at beginning of transition
        next -- attempted new state
        message -- explanation of why the specific transition is not allowed
    """
 
    def __init__(self, previous, next, message):
        self.previous = previous
        self.next = next
        self.message = message

6、定义清理行为

try - finally语句中的finally语句定义了无论在任何情况下都会执行的清理行为

# 6、定义清理行为
def divide(x, y):
    try:
        result = x / y
    except ZeroDivisionError as ZDE:
        print("division by zero!!!:{0}".format(ZDE))
    else:
        print("result is:", result)
    finally:
        print("executing finally clause")

divide(2 , 1)
divide(2 , 0)
result is: 2.0
executing finally clause
division by zero!!!:division by zero
executing finally clause

7、预定义的清理行为

某些对象定义了标准的清理行为,无论系统是否成功的使用了它,一旦不需要它了,那么这个标准的清理行为就会执行,如关键词 with 语句就可以保证文件之类的对象在使用完之后一定会正确的执行它的清理方法(关闭文件)

with open("myfile.txt") as f:
    for line in f:
        print(line, end="")

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值