处理python异常

简介: 本文介绍了Python中的异常处理机制,并实现了一个简单的异常装饰器。通过`try/except`语句捕获异常,结合`finally`子句完成清理工作。为进一步优化代码结构,文章提出了使用装饰器处理异常的方法,避免函数中大量冗长的异常处理语句。通过类封装异常装饰器,多个函数可共享异常处理逻辑,提升代码简洁性和可维护性。总结强调了装饰器在异常处理中的优势,使代码更加优雅高效。

异常基础

在python代码中捕获异常,可以使用try/except语句。它的基本形式如下:

python

体验AI代码助手

代码解读

复制代码

try:    
# 需要检查的代码
except Exception as e:    
# 处理异常的代码

还可以使用finally子句,在异常发生时执行一些清理工作,以及不管是否发生异常都要执行的操作。

python

体验AI代码助手

代码解读

复制代码

try:
# 需要检查的代码
except Exception as e:
# 处理异常的代码
finally:
# 不管是否发生异常都要执行的代码

此外,在except子句中,可以根据不同的异常类型使用不同的处理方式,以便更加精确地处理异常。

python

体验AI代码助手

代码解读

复制代码

try:
    # 需要检查的代码
except ValueError as e:
    # 处理ValueError异常的代码
except TypeError as e:
    # 处理TypeError异常的代码
except Exception as e:
    # 处理其他异常的代码

可以发现,为了给一个方法添加异常处理,需要在方法中添加大量的try/except语句,这样会使代码变得很冗长,不易阅读。因此,笔者尝试一种更加优雅的方式来处理异常。

异常处理装饰器

笔者的初步构思是我只需要给需要捕捉异常的函数添加一个装饰器,随后我们可以将该函数的各类异常分离出来,统一处理。这样就可以避免在函数中添加大量的try/except语句。

python

体验AI代码助手

代码解读

复制代码

# 伪代码

@tryme
def func():
    # 需要检查的代码
    print(1 / 0)

@func.exception(ZeroDivisionError)
def handle_zero_division_error(e):
    # 处理ZeroDivisionError异常的代码
    print(e)

这样,当func函数发生ZeroDivisionError异常时,就会调用handle_zero_division_error函数来处理异常。

观察以上伪代码,首先我们在func函数上添加了一个装饰器@tryme,这点不难理解,而后面我们添加异常装饰器是使用@func.exception,但是我们的func函数并没有exception属性,这是怎么回事呢?其实这也不难,我们只需要在@tryme的装饰器中,将func函数的exception属性指向一个新的函数,这个函数的作用就是添加异常处理函数。

代码实现

less

体验AI代码助手

代码解读

复制代码

from functools import wraps
from typing import Callable, Dict, Any


def tryme(func):
    exception_: Dict[Any, Callable] = {}

    @wraps(func)
    def wrapper(*args, **kwargs):
        try:
            ret = func(*args, **kwargs)
            if ret is not None:
                return ret
        except Exception as e:
            handler = None
            for c in exception_.keys():
                if isinstance(e, c):
                    handler = c

            if handler is None:
                raise e

            return exception_[handler](e)

    def except_(*exceptions):
        def decorator(f):
            for e in exceptions:
                exception_[e] = f
            return f

        return decorator
    # 将exception属性指向except_函数
    # 这样就可以使用@func.exception来添加异常处理函数
    wrapper.exception = except_
    return wrapper


@tryme
def my_function():
    print(1 / 0)


@my_function.exception(ZeroDivisionError)
def handle_zero_division_error(e):
    print('zero division error')


if __name__ == '__main__':
    my_function()

这一版本中有个不太合理的地方,假设我有10个函数需要捕捉某个指定异常,岂不是要写10次@my_function.exception(ZeroDivisionError)?这样的代码显然不够优雅,因此我们需要改进一下。使用类来封装异常装饰器,同一实例化的对象可以共享异常处理函数。

python

体验AI代码助手

代码解读

复制代码

from functools import wraps
from typing import Callable, Dict, Any


class TryMe:

    def __init__(self):
        self.exception_: Dict[Any, Callable] = {}

    def try_(self, func):

        @wraps(func)
        def wrapper(*args, **kwargs):
            try:
                return func(*args, **kwargs)
            except Exception as e:
                handler = None
                for c in self.exception_.keys():
                    if isinstance(e, c):
                        handler = c

                if handler is None:
                    raise e
                # 将异常发生的函数和异常对象传入异常处理函数
                return self.exception_[handler](func, e)

        return wrapper

    def except_(self, *exceptions):
        def decorator(f):
            for e in exceptions:
                self.exception_[e] = f
            return f

        return decorator


tryme = TryMe()


@tryme.try_
def my_function():
    print(1 / 0)
    print('hello world')


@tryme.try_
def my_function2():
    print(1 / 0)
    print('hello world')


@tryme.except_(ZeroDivisionError)
def handle_zero_division_error(func, e):
    print(func.__name__, str(e))


if __name__ == '__main__':
    my_function()
    my_function2()

csharp

体验AI代码助手

代码解读

复制代码

输出:
my_function division by zero
my_function2 division by zero

这样,我们可以统一封装异常函数,由于调用异常函数时,会传入异常发生的函数和异常对象,因此我们可以在异常函数中获取异常发生的函数的信息,比如函数名、参数等。

总结

本文不仅介绍了Python中的异常处理机制,还实现了一个简单的异常装饰器。面对多个异常需要在函数后追加各种except语句,显得代码不够优雅,因此我们可以使用装饰器来实现异常处理,这样可以使代码更加简洁。


转载来源:https://juejin.cn/post/7181320022021636155

相关文章
|
3月前
|
运维 监控 算法
时间序列异常检测:MSET-SPRT组合方法的原理和Python代码实现
MSET-SPRT是一种结合多元状态估计技术(MSET)与序贯概率比检验(SPRT)的混合框架,专为高维度、强关联数据流的异常检测设计。MSET通过历史数据建模估计系统预期状态,SPRT基于统计推断判定偏差显著性,二者协同实现精准高效的异常识别。本文以Python为例,展示其在模拟数据中的应用,证明其在工业监控、设备健康管理及网络安全等领域的可靠性与有效性。
661 13
时间序列异常检测:MSET-SPRT组合方法的原理和Python代码实现
|
2月前
|
Python
如何处理python的常见异常问题
在Python语言中,python异常处理机制主要依赖try、except、else、finally和raise五个关键字。本篇文章将为大家详细讲解一下如何处理python的常见异常问题。
|
4月前
|
人工智能 Shell 开发工具
[oeasy]python065python报错怎么办_try_试着来_except_发现异常
本文介绍了Python中处理异常的基本方法,重点讲解了`try`和`except`的用法。通过一个计算苹果重量的小程序示例,展示了如何捕获用户输入错误并进行处理。主要内容包括: 1. **回顾上次内容**:简要回顾了Shell环境、Python3游乐场和Vim编辑器的使用。 2. **编写程序**:编写了一个简单的程序来计算苹果的总重量,但发现由于输入类型问题导致结果错误。 3. **调试与修正**:通过调试发现输入函数返回的是字符串类型,需要将其转换为整数类型才能正确计算。
91 32
|
4月前
|
数据库 Python
[oeasy]python066_如何捕获多个异常_try_否则_else_exception
本文介绍了Python中`try...except...else`结构的使用方法。主要内容包括: 1. **回顾上次内容**:简要复习了`try`和`except`的基本用法,强调了异常处理的重要性。 2. **详细解释**: - `try`块用于尝试执行代码,一旦发现错误会立即终止并跳转到`except`块。 - `except`块用于捕获特定类型的异常,并进行相应的处理。 - `else`块在没有异常时执行,是可选的。 3. **示例代码**:通过具体例子展示了如何捕获不同类型的异常(如`ValueError`和`ZeroDivisionError`),并解释了异常处理
108 24
|
7月前
|
测试技术 开发者 Python
对于Python中的异常要如何处理,raise关键字你真的了解吗?一篇文章带你从头了解
`raise`关键字在Python中用于显式引发异常,允许开发者在检测到错误条件时中断程序流程,并通过异常处理机制(如try-except块)接管控制。`raise`后可跟异常类型、异常对象及错误信息,适用于验证输入、处理错误、自定义异常、重新引发异常及测试等场景。例如,`raise ValueError("Invalid input")`用于验证输入数据,若不符合预期则引发异常,确保数据准确并提供清晰错误信息。此外,通过自定义异常类,可以针对特定错误情况提供更具体的信息,增强代码的健壮性和可维护性。
|
8月前
|
存储 索引 Python
Python生成器、装饰器、异常(2)
【10月更文挑战第16天】
101 1
Python生成器、装饰器、异常(2)
|
7月前
|
Python
在Python中,`try...except`语句用于捕获和处理程序运行时的异常
在Python中,`try...except`语句用于捕获和处理程序运行时的异常
181 5
|
7月前
|
Python
在Python中,自定义函数可以抛出自定义异常
在Python中,自定义函数可以抛出自定义异常
140 5
|
7月前
|
存储 开发者 Python
自定义Python的异常
自定义Python的异常
117 5
|
8月前
|
Python
Python生成器、装饰器、异常
【10月更文挑战第15天】
61 2

热门文章

最新文章

推荐镜像

更多