知行编程网知行编程网  2022-10-21 14:30 知行编程网 隐藏边栏  18 
文章评分 0 次,平均分 0.0
导语: 本文主要介绍了关于Python超级详细的raise用法的相关知识,希望可以帮到处于编程学习途中的小伙伴

Python超详raise用法

当程序发生错误时,系统会自动抛出异常。此外,Python 还允许程序自己引发异常,这可以使用 raise 语句来完成。

在很多情况下,系统是否应该引发异常可能需要根据应用的业务需求来确定。如果程序中的数据和执行与既定的业务需求不匹配,这是一个例外。由于与业务需求不一致而产生的异常必须由程序员引发,系统不能引发此类异常。

如果你需要自己在程序中引发异常,则应使用 raise 语句。 raise 语句的三种常见用法:

raise:单次加薪。此语句引发在当前上下文中捕获的异常(例如在 except 块中),或者默认情况下引发 RuntimeError 异常。

引发异常类:引发异常类。该语句抛出指定异常类的默认实例。

raise 异常对象:引发指定的异常对象。

以上三种用法最终都是为了引发一个异常实例(即使指定了异常类,实际上也是该类的默认实例),而raise语句一次只能引发一个异常实例。

你可以使用 raise 语句重写之前五子棋游戏中处理用户输入的代码:

try :
    #将用户输入的字符串以逗号( ,)作为分隔符,分隔成两个字符串
    x_str, y_str = inputStr.split(sep =",")
    #如果要下棋的点不为空
    if board[int(y_str) - 1] [int(x_str) - 1] != "+":
    #引发默认的RuntimeError异常
    raise
    #把对应的列表元素赋为”●”
    board [int(y_str) - 1] [int(x_str) - 1] = ”●”
except Exception as e:
    print (type(e))
    inputStr = input("你输入的坐标不合法,请重新输入,下棋坐标应以x,y 的格式\n")
    continue

上述程序中的第 7 行代码使用 raise 语句自行引发异常。当用户尝试使用现有棋子的坐标下棋时,程序认为这是一个例外。当 Python 解释器接收到开发者提出的异常时,它也会中止当前的执行流程,并跳转到异常对应的 except 块,该块将处理该异常。也就是说,无论是系统自动引发的异常,还是程序员自动引发的异常,Python解释器对异常的处理没有任何区别。

即使是用户引发的异常也可以用 try except 来捕获。当然,你可以不理会它,让异常向上传播(调用者优先),如果将异常传递给 Python 解释器,程序将中止。

以下示例演示了两种处理用户引发的异常的方法:

def main():
    try:
        # 使用try...except来捕捉异常
        # 此时即使程序出现异常,也不会传播给main函数
        mtd(3)
    except Exception as e:
        print('程序出现异常:', e)
    # 不使用try...except捕捉异常,异常会传播出来导致程序中止
    mtd(3)
def mtd(a):
    if a > 0:
        raise ValueError("a的值大于0,不符合要求")
main()

从上面的程序可以看出,程序在调用mtd(3)时既可以使用try except来捕捉异常,这样异常就会被except块捕捉到,不会传播到调用它的函数中;你也可以直接调用 mtd(3 ),以便将函数的异常直接传播到其调用函数,如果该函数也不处理异常,则会导致程序中止。

运行上面程序,可以看到如下输出结果:

程序出现异常: a的值大于0,不符合要求
Traceback (most recent call last):
  File "C:\Users\mengma\Desktop\1.py", line 13, in <module>
    main()
  File "C:\Users\mengma\Desktop\1.py", line 9, in main
    mtd(3)
  File "C:\Users\mengma\Desktop\1.py", line 12, in mtd
    raise ValueError("a的值大于0,不符合要求")
ValueError: a的值大于0,不符合要求

上面的第一行输出是第一次调用 mtd(3) 的结果,它引发了一个异常,该异常被 except 块捕获和处理。接下来的大部分输出是第二次调用 mtd(3) 的结果。由于异常没有被 except 块捕获,异常向上传播,直到它被传递给 Python 解释器并且程序中止。

第二次调用mtd(3)导致的以“File”开头的三行输出实际上显示了异常传播轨迹信息。也就是说,如果程序不处理异常,Python会默认将异常传播轨迹信息输出到控制台。


自定义异常类

很多时候,程序选择引发自定义异常,因为异常的类名通常还包含有关异常的有用信息。所以当抛出异常时,应该选择一个合适的异常类,以便能清楚地描述异常。在这种情况下,应用程序通常需要引发自定义异常。

用户定义的异常应该继承自 Exception 基类或 Exception 的子类。自定义异常类的时候基本不用多写代码,只要指定自定义异常类的父类即可。

下面程序创建了一个自定义异常类(程序一):

class AuctionException(Exception): pass

上面的程序创建了AuctionException异常类,不需要类体定义,所以使用pass语句作为占位符。

在大多数情况下,创建自定义异常类可以使用类似于程序1的代码完成,只需更改AuctionException异常的类名,以便异常的类名能够准确描述异常。


except 和 raise 同时使用

在实际应用中,异常可能需要更复杂的处理。当异常发生时,仅靠一个方法是无法完全处理异常的,必须多个方法配合才能完全处理异常。也就是说,在当前发生异常的方法中,程序只是对异常进行了部分处理,有些处理需要在方法的调用者中完成,所以要再次引发异常,让调用者方法也可以捕捉到它的异常。

为了实现这种多个方法协同处理同一个异常的情况,可以结合一个异常块中的raise语句来完成。下面的程序演示了 except 和 raise 的用法:

class AuctionException(Exception): pass
class AuctionTest:
    def __init__(self, init_price):
        self.init_price = init_price
    def bid(self, bid_price):
        d = 0.0
        try:
            d = float(bid_price)
        except Exception as e:
            # 此处只是简单地打印异常信息
            print("转换出异常:", e)
            # 再次引发自定义异常
            raise AuctionException("竞拍价必须是数值,不能包含其他字符!")  # ①
            raise AuctionException(e)
        if self.init_price > d:
            raise AuctionException("竞拍价比起拍价低,不允许竞拍!")
        initPrice = d
def main():
    at = AuctionTest(20.4)
    try:
        at.bid("df")
    except AuctionException as ae:
        # 再次捕获到bid()方法中的异常,并对该异常进行处理
        print('main函数捕捉的异常:', ae)
main()

上述程序第9~13行对应的except块中捕获到异常后,系统打印异常的字符串信息,然后引发AuctionException异常,通知调用方再次处理AuctionException异常的方法。因此,程序中的main()函数,也就是bid()方法的调用者,也可以再次捕捉到AuctionException异常,并打印出异常的详细描述。

这种 except 和 raise 的组合在实际应用中非常常见。实际应用中对异常的处理通常分为两部分:

应用后台需要通过日志记录异常的细节;

应用程序还需要根据异常向应用程序用户传达某种提示;

在这种情况下,所有的异常都需要两个方法来完成,这意味着except和raise必须一起使用。

如果程序需要直接传播原始异常的细节,Python也允许用自定义异常来包装原始异常,只要将上面的代码①改成如下形式即可:

raise AuctionException(e)


raise 不需要参数

如前所述,raise 语句可以不带参数使用。此时raise语句在一个except块中,它会自动抛出当前上下文中激活的异常;否则,它通常会默认引发 RuntimeError 异常。

例如,将上面程序改为如下形式:

class AuctionException(Exception): pass
class AuctionTest:
    def __init__(self, init_price):
        self.init_price = init_price
    def bid(self, bid_price):
        d = 0.0
        try:
            d = float(bid_price)
        except Exception as e:
            # 此处只是简单地打印异常信息
            print("转换出异常:", e)
            # 再次引发自定义异常
            raise
        if self.init_price > d:
            raise AuctionException("竞拍价比起拍价低,不允许竞拍!")
        initPrice = d
def main():
    at = AuctionTest(20.4)
    try:
        at.bid("df")
    except AuctionException as ae:
        # 再次捕获到bid()方法中的异常,并对该异常进行处理
        print('main函数捕捉的异常:', ae)
main()

从第 13 行可以看出,程序只是在 except 块中使用 raise 语句来引发异常,raise 语句将重新引发 except 块捕获的异常。运行程序,可以看到如下输出:

转换出异常: could not convert string to float: 'df'
main 函数捕获的异常:<class 'ValueError'>

从输出中,main() 函数再次捕获 ValueError,这是 bid() 方法中的 except 块捕获的原始异常。

本文为原创文章,版权归所有,欢迎分享本文,转载请保留出处!

知行编程网
知行编程网 关注:1    粉丝:1
这个人很懒,什么都没写
扫一扫二维码分享