【Python从入门到精通】异常详解

 Why do Python programmers prefer dark mode? 
Because light attracts bugs.

Python的简洁性和易读性,认为这是吸引Python程序员的原因。

【Python从入门到精通】专栏课程:

1、【Python从入门到精通】认识Python

2、【Python从入门到精通】变量&数据类型

3、【Python从入门到精通】列表&元组&字典&集合

4、【Python从入门到精通】运算符&控制语句

 一、异常

在Python中,异常是指在程序执行过程中出现的错误或异常情况。异常可能由于程序错误、无效的输入、系统故障或其他不可预测的情况而引发,也就是说因为某些原因引发程序中断,当然一些异常可以处理一些异常是我们处理不了的。

1.1 异常类

在Python中,异常可以分为两大类:运行时异常(Runtime Exceptions)和非运行时异常(Non-Runtime Exceptions)。

注意:异常是一个类,当程序执行过程中出现异常情况就会创建对应异常对象并抛出中断程序的运行,我们可以通过这些异常对象访问有关异常的信息以及处理异常的相关机制。

Python中,所有异常的父类是BaseException类。BaseException类是Python异常层次结构中的最顶层的异常类,所有内置的和自定义的异常都是它的子类或间接子类。

BaseException是所有异常类的根类,它定义了异常的基本行为和属性。Exception是大多数Python异常的直接基类,它包括了绝大多数通常会遇到的异常类型。其他更具体的异常类则是Exception的子类,它们进一步细化了异常类型,以便更好地对不同类型的异常进行处理。

class Exception(BaseException):
    """ Common base class for all non-exit exceptions. """
    def __init__(self, *args, **kwargs): # real signature unknown
        pass

    @staticmethod # known case of __new__
    def __new__(*args, **kwargs): # real signature unknown
        """ Create and return a new object.  See help(type) for accurate signature. """
        pass
class BaseException(object):
    """ Common base class for all exceptions """
    def with_traceback(self, tb): # real signature unknown; restored from __doc__
        """
        Exception.with_traceback(tb) --
            set self.__traceback__ to tb and return self.
        """
        pass

    def __delattr__(self, *args, **kwargs): # real signature unknown
        """ Implement delattr(self, name). """
        pass

    def __getattribute__(self, *args, **kwargs): # real signature unknown
        """ Return getattr(self, name). """
        pass

    def __init__(self, *args, **kwargs): # real signature unknown
        pass

    @staticmethod # known case of __new__
    def __new__(*args, **kwargs): # real signature unknown
        """ Create and return a new object.  See help(type) for accurate signature. """
        pass

    def __reduce__(self, *args, **kwargs): # real signature unknown
        pass

    def __repr__(self, *args, **kwargs): # real signature unknown
        """ Return repr(self). """
        pass

    def __setattr__(self, *args, **kwargs): # real signature unknown
        """ Implement setattr(self, name, value). """
        pass

    def __setstate__(self, *args, **kwargs): # real signature unknown
        pass

    def __str__(self, *args, **kwargs): # real signature unknown
        """ Return str(self). """
        pass

    args = property(lambda self: object(), lambda self, v: None, lambda self: None)  # default

    __cause__ = property(lambda self: object(), lambda self, v: None, lambda self: None)  # default
    """exception cause"""

    __context__ = property(lambda self: object(), lambda self, v: None, lambda self: None)  # default
    """exception context"""

    __suppress_context__ = property(lambda self: object(), lambda self, v: None, lambda self: None)  # default

    __traceback__ = property(lambda self: object(), lambda self, v: None, lambda self: None)  # default


    __dict__ = None # (!) real value is "mappingproxy({'__repr__': <slot wrapper '__repr__' of 'BaseException' objects>, '__str__': <slot wrapper '__str__' of 'BaseException' objects>, '__getattribute__': <slot wrapper '__getattribute__' of 'BaseException' objects>, '__setattr__': <slot wrapper '__setattr__' of 'BaseException' objects>, '__delattr__': <slot wrapper '__delattr__' of 'BaseException' objects>, '__init__': <slot wrapper '__init__' of 'BaseException' objects>, '__new__': <built-in method __new__ of type object at 0x00007FFCDC93E070>, '__reduce__': <method '__reduce__' of 'BaseException' objects>, '__setstate__': <method '__setstate__' of 'BaseException' objects>, 'with_traceback': <method 'with_traceback' of 'BaseException' objects>, '__suppress_context__': <member '__suppress_context__' of 'BaseException' objects>, '__dict__': <attribute '__dict__' of 'BaseException' objects>, 'args': <attribute 'args' of 'BaseException' objects>, '__traceback__': <attribute '__traceback__' of 'BaseException' objects>, '__context__': <attribute '__context__' of 'BaseException' objects>, '__cause__': <attribute '__cause__' of 'BaseException' objects>, '__doc__': 'Common base class for all exceptions'})"

1.1.1 运行时异常

运行时异常是指在程序运行期间检测到的错误,通常是由于程序逻辑错误、无效的数据操作或异常条件引起的,运行时异常是可以通过某种手段解决的,从而确保程序在发生异常时能够优雅地处理而不崩溃。

常见的运行时异常如下所示:

ZeroDivisionError(除零错误):

当我们在完成除法运算时,若除数为0那么就会触发该异常。

print(6 / 0)
print(123)

TypeError(类型错误):

当操作或函数应用于不适当类型的对象时引发的异常。

# Python是强类型语言,数字和字符串不能直接相加
print(1 + "12")

ValueError(值错误):

当一个函数收到的参数类型正确但值不合法时引发的异常。

print(int("hello world"))

IndexError(索引错误):

当尝试访问序列中不存在的索引时引发的异常。

list1 = [1,2,3,4]
print(list1[6])

KeyError(键错误):

当尝试在字典中访问不存在的键时引发的异常。

student = {'name':'join'}
print(student['age'])

AttributeError(属性错误):

当尝试访问不存在的对象属性时引发的异常。

class MyClass:
    pass

obj = MyClass()
print(obj.attribute)

FileNotFoundError(文件未找到错误):

当尝试访问不存在的文件时引发的异常。

with open("1.txt", "r") as file:
    content = file.read()

NameError(名称错误):

当尝试访问一个不存在的变量或函数名时引发的异常。

print(a)

 1.1.2 非运行时异常

非运行时异常是指在程序运行期间以外的阶段就能够被检测到的错误,主要包括语法错误(SyntaxError)。语法错误是在编写代码时就由Python解释器检测到的问题,它们阻止程序的解释和执行。与运行时异常不同,非运行时异常发生在程序执行之前,因此我们是干预不了的。

# 语法错误示例,缺少冒号
if True
    print("Hello, World!")

1.2 异常处理机制 

Python的异常处理机制允许程序在异常情况下采取措施,以便优雅地处理问题并继续执行。异常处理机制主要通过try、except、else、finally等关键字来实现。

1.2.1 try-except模块

  • try模块中包含可能引发异常的代码。
  • 如果try块中的代码引发了异常,则控制流会立即转移到与异常匹配的except块。
  • except块用于指定要处理特定异常的代码。
try:
    # 可能会引发异常的代码
    result = 10 / 0
except ZeroDivisionError:
    # 处理 ZeroDivisionError 异常的代码
    print("Error: Division by zero")

当然在一个try语句中可以包含多个except块,每个except块用于处理不同类型的异常。

try:
    result = 10 / 0
except TypeError as t:
    print('Error:TypeError')
except ZeroDivisionError:
    print("Error: Division by zero")

补充:如果异常在当前的try块中没有被处理,则会将其传播到上一级调用的try块或全局范围,直到被处理或导致程序终止。 

1.2.2 try-except-else模块 

可选的else块在try块中的代码未引发任何异常时执行,else块通常用于在没有异常发生时执行一些附加操作。

try:
    result = 10
except TypeError as t:
    print('Error:TypeError')
else:
    print('没有任何异常发生')

注意: try不能和else单独使用。

try:
    result = 10
else:
   print('123')

1.2.3 finally块

可选的finally块始终在try块中的代码执行完毕后执行,无论是否发生异常。finally块通常用于执行清理操作,例如关闭文件或释放资源。

try:
    result = 10
finally:
    print("finally")

try:
    result = 10 / 0
except ZeroDivisionError:
    print("ZeroDivisionError")
finally:
    print("finally")

1.3 raise抛出异常 

上述我们说过若程序中出现异常情况,那么就会创建对应异常对象并抛出,除此之外,我们也可以主动将异常给抛出去,在Python中,我们可以使用raise语句手动抛出异常。raise语句用于引发特定类型的异常,可以是内置的异常类,也可以是自定义的异常类。

raise ExceptionType("Error message")

上述代码中其中,ExceptionType是异常类的名称,可以是Python内置的异常类(如TypeError等),也可以是自定义的异常类,而"Error message"是异常消息,它描述了异常的具体信息。

注意:手动抛出异常的情况通常是在编写函数或类时,发现某些不符合预期的情况,需要向调用者报告错误。通过手动抛出异常,可以让代码更加清晰地表达异常情况,并且提供有用的错误信息,以便调用者能够更好地理解和处理异常。

name = None

if name is None:
    raise Exception("Name cannot be None")

 1.4 自定义异常

在Python中,你可以通过创建新的异常类来自定义异常。自定义异常类可以继承自内置的异常类(如BaseException或Exception),也可以直接继承自其他异常类(如ValueError),或者你可以定义一个完全新的异常类。

class MyCustomError(Exception):
  
    def __init__(self, message="An error occurred"):
        self.message = message
        super().__init__(self.message)

在上述代码中,我们创建了一个名为MyCustomError的自定义异常类,它继承自Exception类。在异常类的构造函数中,我们定义了一个可选参数message,用于指定异常的错误消息。如果未提供错误消息,则默认为"An error occurred"。

class MyCustomError(Exception):

    def __init__(self, message="An error occurred"):
        self.message = message
        super().__init__(self.message)

def divide(x, y):
    if y == 0:
        raise MyCustomError("Division by zero is not allowed")
    else:
        return x / y

try:
    result = divide(10, 0)
except MyCustomError as e:
    print("Error:", e)

 1.5 BaseException类解析

BaseException是Python异常层次结构中的基类,它包含了一些常用的属性和方法。以下是BaseException的一些主要属性和方法的解析:

  • args属性是一个元组,包含了异常实例的参数,默认情况下,BaseException类的构造函数会将传递给异常的参数存储在args属性中。
  • with_traceback方法用于设置异常的回溯对象(traceback),回溯对象是一个保存有关异常发生位置和上下文的信息的数据结构,该方法返回异常对象本身,允许在抛出异常的同时设置回溯信息。
  • __repr__方法用于返回对象的“官方”字符串表示形式,通常用于调试和诊断目的。
  • __str__方法用于返回对象的“非官方”字符串表示形式,通常用于显示给终端用户。
try:
    x = 10 / 0
except ArithmeticError as e:
    print(e)
    print('---------------')
    print(e.args)
    print('-------------------')
    print(e.__repr__())
    print('-------------------')
    print(e.__str__())

 1.6 异常信息跟踪栈

在 Python 中,可以使用traceback 模块来打印异常信息的跟踪栈(traceback stack)。跟踪栈提供了异常发生的位置以及调用链中的各个函数或模块。

import traceback

try:
    # 代码中出现异常
    a = 1 / 0
except Exception as e:
    # 打印异常信息和跟踪栈
    print("Exception caught:", e)
    traceback.print_exc()

好了关于异常的知识点到此为止,看完教程之后是不是很简单,下期教程将继续学习Python中的函数。

关于Python更多的内容可以关注《Python从入门到精通》,该专栏主要用于分享Python学习教程,该系列教程只有干货没有花里胡哨,欢迎大家一起来学习探讨一起进步。

  • 33
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值