Python中的异常处理raise介绍

0. 介绍

问题1: 是否可以在程序的指定位置手动抛出一个异常

答案是肯定的,Python 允许我们在程序中手动设置异常,使用 raise 语句即可。

问题2: 我们从来都是想方设法地让程序正常运行,为什么还要手动设置异常呢?

首先要分清楚程序发生异常和程序执行错误,它们完全是两码事,程序由于错误导致的运行异常,是需要程序员想办法解决的;但还有一些异常,是程序正常运行的结果,比如用 raise 手动引发的异常(比如1÷0没有意义,程序没有写错,但是这样运算不合理,就是异常)。

raise 语句的基本语法格式为:

raise [exceptionName [(reason)]]

其中,用 [] 括起来的为可选参数,其作用是指定抛出的异常名称,以及异常信息的相关描述

如果可选参数全部省略,则 raise 会把当前错误原样抛出;如果仅省略 (reason),则在抛出异常时,将不附带任何的异常描述信息。

也就是说,raise 语句有如下三种常用的用法:

  • raise:单独一个 raise。该语句引发当前上下文中捕获的异常(比如在 except 块中),或默认引发 RuntimeError 异常。
  • raise 异常类名称:raise 后带一个异常类名称,表示引发执行类型的异常。
  • raise 异常类名称(描述信息):在引发指定类型的异常的同时,附带异常的描述信息。

代码测试

>>> raise
Traceback (most recent call last):
  File "<pyshell#1>", line 1, in <module>
    raise
RuntimeError: No active exception to reraise
>>> raise ZeroDivisionError
Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    raise ZeroDivisionError
ZeroDivisionError
>>> raise ZeroDivisionError("除数不能为零")
Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    raise ZeroDivisionError("除数不能为零")
ZeroDivisionError: 除数不能为零

1. raise 介绍(案例)

程序正常运行的时候,根据需要,用 raise 手动引发异常。

raise 语句引发的异常,通常用 try exceptelse finally)异常处理结构来捕获并进行处理。例如:

try:
    a = input("输入一个数:")
    #判断用户输入的是否为数字
    if(not a.isdigit()):
        raise ValueError("a 必须是数字")
except ValueError as e:
    print("引发异常:", repr(e))

当我们输入字母 a ,程序运行结果为:

runfile('E:/09-code/01-turbulence/test/test04.py', wdir='E:/09-code/01-turbulence/test')
输入一个数:>? a
引发异常: ValueError('a 必须是数字')

当我们输入数字 8,程序运行结果为:

输入一个数:8

由上面示例可以看出,我们手动让程序引发异常,很多时候并不是为了让其崩溃。

2. raise 不需要参数(案例)

这里重点关注位于 except 块中的 raise

try:
    a = input("输入一个数:")
    if(not a.isdigit()):
        raise ValueError("a 必须是数字")
except ValueError as e:
    print("引发异常:", repr(e))
    raise

由于在其之前我们已经手动引发了 ValueError 异常,因此这里当再使用 raise 语句时,它会再次引发一次。当我们输入字母 a ,程序执行结果为:

In[2]: runfile('E:/09-code/01-turbulence/test/test04.py', wdir='E:/09-code/01-turbulence/test')
输入一个数:a
引发异常: ValueError('a 必须是数字',)
Traceback (most recent call last):
  File "D:\python3.6\1.py", line 4, in <module>
    raise ValueError("a 必须是数字")
    
ValueError: a 必须是数字

这里重点关注位于 except 块中的 raise,由于在其之前我们已经手动引发了 ValueError 异常,因此这里当再使用 raise 语句时,它会再次引发一次。

3. raise:单独一个 raise(正常程序使用无参的 raise )

当在没有引发过异常的程序使用无参的 raise 语句时,它默认引发的是 RuntimeError 异常。例如:

try:
    a = input("输入一个数:")
    if(not a.isdigit()):
        raise
except RuntimeError as e:
    print("引发异常:", repr(e))

当我们输入字母 a ,程序执行结果为:

In[3]: runfile('E:/09-code/01-turbulence/test/test04.py', wdir='E:/09-code/01-turbulence/test')
输入一个数:>? a
引发异常: RuntimeError('No active exception to reraise')

4. 其它案例

4.1 案例1

def read_file(file, pattern):
    try:
        if file.endswith('rtd'):
            data = pd.read_csv(file, skiprows=41, sep=r'\t')
        elif file.endswith('csv'):
            data = pd.read_csv(file)
        else:
            raise ValueError("Unknown file type")
        data = extract_cols(data, pattern=pattern, file=file)
    except Exception as e:
        print(f"{os.path.basename(file).split('.')[0]}: {e}")
        data = pd.DataFrame()
    return data

4.2 案例2

def divide(a, b):
    return a/b

try:
    divide(1, 0)
except:
    print("divide by 0")
else:
    print("the code is no problem")

print("code after try catch,hello,world!")

输出结果

divide by 0
code after try catch,hello,world!

5. 处理流程

try:
  code    #需要判断是否会抛出异常的代码,如果没有异常处理,python会直接停止执行程序
 
except:  #这里会捕捉到上面代码中的异常,并根据异常抛出异常处理信息
#except ExceptionName,args:    #同时也可以接受异常名称和参数,针对不同形式的异常做处理
 
  code  #这里执行异常处理的相关代码,打印输出等
 
else#如果没有异常则执行else
 
  code  #try部分被正常执行后执行的代码
 
finally:
  code  #退出try语句块总会执行的程序

可以看到

    1. 这里的 else 是和 try-catch 连用的,并且 else 只在 try 中代码没有异常的情况下执行,else 必须在 except 这句代码存在的时候才能出现。
    1. finally 这个片段里面的代码是肯定在最后执行的,无论前面是否发生异常,最后总会执行finally片段内的代码。
  • 所以,正常的流程是:try 没有发生错误-》else 内的代码-》finally 中的代码。

  • 发生异常的流程是:try 中发生异常-》被 except 捕获并执行 except 片段中的代码-》执行 finally 中的代码。

6. 显示error位置

要在抛出异常时包含代码所在的位置,可以使用Python的traceback模块。这个模块可以获取异常发生时的堆栈信息,包括文件名和行号。

以下是一个示例代码,展示了如何在捕获异常时打印出详细的错误信息,包括代码所在的位置:

import traceback

try:
    # 假设这是可能会抛出异常的代码
    # 例如:result = 10 / 0  # 这将引发ZeroDivisionError
    result = 10 / 0
except Exception as e:
    # 获取异常信息和堆栈跟踪
    tb = traceback.format_exc()
    print(f"Error processing {filename}: {e}\nTraceback:\n{tb}")

在这个示例中,traceback.format_exc()会返回一个字符串,其中包含了异常的详细信息和堆栈跟踪,包括引发异常的文件名和行号。这样,就可以清楚地看到错误发生的位置。😊

错误信息如下:

Error processing : division by zero
Traceback:
Traceback (most recent call last):
  File "<ipython-input-5-6bef8f98af92>", line 6, in <module>
    result = 10 / 0
ZeroDivisionError: division by zero

总结

也就是说,raise 语句有如下三种常用的用法:

1.raise:单独一个 raise。该语句引发当前上下文中捕获的异常(比如在 except 块中),或默认引发 RuntimeError 异常。
2.raise 异常类名称:raise 后带一个异常类名称,表示引发执行类型的异常。
3.raise 异常类名称(描述信息):在引发指定类型的异常的同时,附带异常的描述信息。

参考链接:
链接1

03-15
<think>好的,我需要回答用户关于RAISE关键字在编程或数据库中的用法的问题。首先,我得确定RAISE关键字在不同上下文中的不同应用。记得用户可能指的是编程语言中的异常处理,或者数据库中的触发器或存储过程里的操作。 首先,编程方面,比如Python中的raise语句用于触发异常。用户可能想知道如何抛出异常,自定义异常类型,或者传递异常信息。我需要举几个例子,比如基本的raise ValueError,或者带参数的raise Exception("message")。同时,可能需要提到异常链,比如raise ... from ...的用法。 接下来是SQL领域,特别是像PostgreSQL这样的数据库,RAISE用于在存储过程中输出消息或引发错误。这里需要区分不同的级别,比如NOTICE、WARNING、EXCEPTION,并说明它们的区别和用法。例如,RAISE EXCEPTION会中止事务,而NOTICE只是记录信息。还要给出示例代码,比如在PL/pgSQL中的使用。 然后,用户提供的引用中有些可能相关的信息,比如引用[4]提到状态机的替代方案不好,可能和异常处理有关联?不过可能关系不大。引用[2]关于字符串索引,可能无关。引用[1]关于setattr,也可能无关。但需要确认是否有需要引用的地方。例如,当提到Python中的raise语句时,是否需要引用某个资料?用户给的引用似乎不太相关,可能不需要直接引用,但按照系统指令需要在回答中自然地添加引用标识。这里可能需要检查是否有匹配的内容,如果没有的话,可能不需要添加引用,或者看看是否有相关的。 另外,用户要求生成相关问题,我需要根据RAISE关键字的不同用途来设计问题,例如在编程中的异常处理最佳实践,或者在数据库中的调试方法等。 还需要确保所有数学表达式用$...$格式,独立公式用$$...$$,但当前问题可能不涉及数学公式,所以这部分可能不需要。但需要检查是否有潜在的地方需要用到,比如在例子中的代码是否涉及数学表达式,但看起来不需要。 最后,结构要清晰,分点说明编程和数据库中的用法,并给出示例代码。同时,问题部分需要生成三个相关问题,覆盖不同方面,如用法区别、实际应用场景、调试技巧等。 现在开始组织内容:首先介绍RAISE在编程中的用法,比如Python,然后介绍在数据库中的用法,比如PostgreSQL。每个部分给出说明和代码示例。然后生成相关问题,确保问题覆盖不同方面。同时检查是否需要添加引用,根据用户提供的引用,可能引用[4]提到的是一个不好的例子,但和RAISE可能无关,因此可能不需要引用,但根据系统指令,可能需要在回答中自然地添加引用,所以可能需要检查是否有相关内容。不过可能不需要,因为用户提供的引用可能与问题无关,这种情况下可以不添加引用,或者如果有相关内容才添加。根据示例回答,引用了提供的引用,但当前问题可能没有直接相关的内容,所以可能不需要添加引用标识。但需要再次检查。 例如,在Python中,raise的使用是否和引用中的某个内容相关?比如引用[4]提到的是一个不好的例子,但RAISE的正确用法可能与之对比,但可能不太相关。因此可能不需要引用。所以可能回答中不包含引用标识,但根据系统指令,如果引用了提供的引用,需要添加。因此可能需要调整,确保如果有引用就添加,否则不添加。当前情况下,用户提供的引用似乎不相关,因此可能无需添加,但需要确认。例如,用户引用[4]提到的是状态机的替代方案不好,可能和异常处理的错误使用有关,但不确定。如果无法自然引用,可能不需要。 综上所述,回答应分为编程和数据库两部分,分别说明RAISE的用法,并给出代码示例。然后生成相关问题。确保使用正确的中文,结构清晰,代码格式正确。</think>### RAISE关键字用法解析 RAISE关键字在编程和数据库领域有不同的应用场景,主要涉及异常处理和消息通知机制。 --- #### **编程中的RAISE关键字(异常处理)** 在编程语言(如Python、Ada等)中,`RAISE`通常用于**显式触发异常**,帮助开发者控制错误流程。 1. **基本语法(Python示例)** ```python if x < 0: raise ValueError("数值不能为负数") # 触发特定异常 ``` 2. **自定义异常类型** ```python class CustomError(Exception): pass raise CustomError("自定义错误信息") # 使用自定义异常 ``` 3. **重新抛出异常** ```python try: risky_operation() except Exception as e: print(f"捕获异常: {e}") raise # 重新抛出当前异常 ``` 4. **异常链(Python 3+)** ```python try: open("nonexistent_file.txt") except FileNotFoundError as e: raise RuntimeError("文件操作失败") from e # 关联原始异常 ``` --- #### **数据库中的RAISE关键字(消息与错误控制)** 在SQL(如PostgreSQL的PL/pgSQL)中,`RAISE`用于**输出日志消息**或**强制终止事务**。 1. **消息级别** - `NOTICE`:输出提示信息(不影响事务) ```sql RAISE NOTICE '当前用户: %', current_user; -- 输出用户信息 ``` - `WARNING`:生成警告(事务继续) - `EXCEPTION`:触发错误并回滚事务 ```sql RAISE EXCEPTION '订单金额无效: %', amount; -- 终止事务 ``` 2. **格式化参数** 使用`%`占位符动态插入变量: ```sql RAISE NOTICE '订单ID % 已处理', order_id; ``` 3. **条件触发** 结合条件语句控制消息: ```sql IF stock < 0 THEN RAISE EXCEPTION '库存不足'; END IF; ``` --- #### **核心区别** | 场景 | 编程语言(如Python) | 数据库(如PostgreSQL) | |------------|-------------------------------|------------------------------| | **目的** | 异常处理与流程控制 | 消息通知或事务终止 | | **效果** | 中断当前代码块并传递异常 | 记录日志或回滚事务 | | **语法** | `raise Exception("消息")` | `RAISE EXCEPTION '消息'` | ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值