美文网首页视觉艺术python
Python 中更优雅的异常处理方案

Python 中更优雅的异常处理方案

作者: 羋学僧 | 来源:发表于2020-03-31 17:21 被阅读0次

Python 中更优雅的异常处理方案

实例引入

比如写 Python 的时候,举个最简单的算术运算和文件写入的例子,代码如下:

def process(num1,num2,file):

    result = num1 / num2
    with open(file,'w',encoding='utf-8') as f:
        f.write(str(result))

这里我们定义了一个 process 方法,接收三个参数,前两个参数是 num1 和 num2,第三个参数是 file。这个方法会首先将 num1 除以 num2,然后把除法的结果写入到 file 文件里面。

就这么一个简单的操作,但是这个实现真的是漏洞百出:
  • 没有判断 num1、num2 的类型,如果不是数字类型,那会抛出 TypeError。
  • 没有判断 num2 是不是 0,如果是 0,那么会抛出 ZeroDivisionError。
  • 没有判断文件路径是否存在,如果是子文件夹下的路径,文件夹不存在的话,会抛出 FileNotFoundError。
一些异常测试用例如下:
process(1, 2, 'result/result.txt')
process(1, 0, 'result.txt')
process(1, [2], 'result.txt')
如果把这几类的错误都进行异常处理的话,会写成什么样子呢?
def process_try(num1,num2,file):
    
    try:
        result = num1 / num2
        with open(file,'w',encoding='utf-8') as f:
            f.write(str(result))
    except ZeroDivisionError:
        print(f'{num2} can not be zero')
    except FileNotFoundError:
        print(f'file {file} not found')
    except Exception as e:
        print(f'except, {e.args}')

这时候我们观察到了什么问题?

  • 代码一下子臃肿了起来,这里的异常处理都没有实现,仅仅是 print 了一些错误信息,但现在可以看到我们的异常处理代码可能比主逻辑还要多。
  • 主逻辑代码整块被硬生生地缩进进去了,如果主逻辑代码比较多的话,那么会有大片大片的缩进。
  • 如果再有相同的逻辑的代码,难道要再写一次 try except 这一坨代码吗?
可能很多人都在面临这样的困扰,觉得代码很难看但又不知道怎么修改。
当然上面的代码写法本身就不好,有几种改善的方案:
  • 本身这个场景不需要这么多异常处理,使用判断条件把一些意外情况处理掉就好。
  • 异常处理本身就不应该这么写,每个功能区域应该和异常处理单独分开,另外各个逻辑模块建议再分方法解耦。
  • 使用 retrying 模块检测异常并进行重试。
  • 使用上下文管理器 raise_api_error 来声明异常处理。

但上面的一些解决方案其实还不能彻底解决代码复用和美观上的问题,比如某一类的异常处理我就统一在一个地方处理,另外我的任何代码都不想因为异常处理产生缩进。
下面我们来了解一个库,叫做 Merry。

Merry

Merry,这个库是 Python 的一个第三方库,非常小巧,它实现了几个装饰器。通过使用 Merry 我们可以把异常检查和异常处理的代码分开,并可以通过装饰器来定义异常检查和处理的逻辑。

GitHub 地址:https://github.com/miguelgrinberg/merry,这个库的安装非常简单,使用 pip3 安装即可:

pip install merry

官方案例

入门

以这个函数为例,该函数嵌入了错误处理代码:

def write_to_file(filename, data):
    try:
        with open(filename, 'w') as f:
            f.write(data)
    except IOError:
        print('Error: can't write to file')
    except Exception as e:
        print('Unexpected error: ' + str(e))

write_to_file('some_file', 'some_data')

即使使用这个简单的示例,您也可以看到try / except块强制执行的缩进如何使代码更难阅读和可视化。

Merry允许您将异常处理程序移至外部函数,以使它们不会干扰应用程序逻辑:

from merry import Merry

merry = Merry()

@merry._try
def write_to_file(filename, data):
    with open(filename, 'w') as f:
        f.write(data)

@merry._except(IOError)
def ioerror():
    print('Error: can't write to file')

@merry._except(Exception)
def catch_all(e):
    print('Unexpected error: ' + str(e)

write_to_file('some_file', 'some_data')

尽管在此示例中,使用merry后有更多的代码行,但主要好处是该write_to_file 函数中的应用程序逻辑现在完全清除了try / except语句。异常处理程序成为辅助功能,甚至可以移至单独的模块,以使它们完全不受干扰。

访问异常对象

装饰的异常处理程序可以选择接受一个参数。如果包含此参数,则merry发送异常对象。

@merry._except(Exception)
def catch_all(e):
    print('Unexpected error: ' + str(e)

else 和 finally 语法

对于需要更复杂的try / except块的情况,还可以使用装饰器else和finally:

@merry._else
def else_clause():
    print('No exceptions where raised!')

@merry._finally
def finally_clause():
    print('Clean up time!')

Merry详情

使用Merry处理开始的案例

from merry import Merry

merry = Merry()
merry.logger.disabled = True

@merry._try
def process_merry(num1,num2,file):

    result = num1 / num2
    with open(file,'w',encoding='utf-8') as f:
        f.write(str(result))


@merry._except(ZeroDivisionError)
def process_zero_division_error(e):
    print('zero_division_error',e)


@merry._except(FileNotFoundError)
def process_file_not_found_error(e):
    print('process_file_not_found_error', e)


@merry._except(Exception)
def process_exception(e):
    print('process_exception', type(e), e)
    process_try(1, 2, 'result/result.txt')
    process_try(1, 0, 'result.txt')
    process_try(1, [2], 'result.txt')

代码变得更优雅了

学习来源

相关文章

  • Python 中更优雅的异常处理方案

    Python 中更优雅的异常处理方案 实例引入 比如写 Python 的时候,举个最简单的算术运算和文件写入的例子...

  • python基础2

    Python的异常处理机制 Bug的常见类型 被动掉坑的解决方案 python提供了异常处理机制,可以在异常出现时...

  • python异常处理方案

    Traceback (most recent call last):File "D:/shareX/student...

  • Python学习(八)

    异常处理 Python中的异常类型总结: Python内置异常类的层次结构: 异常检测 try-except语句 ...

  • Python异常处理

    参考 Python菜鸟教程错误与异常 Python 异常处理 错误和异常 Python中(至少)有两种错误:语法错...

  • 2020-06-27【异常】

    异常体系 JVM的默认处理方案 异常处理 自定义异常

  • Python中的异常处理

    异常介绍 先来看一个最简单的异常,输出一个没有定义的变量: 那么上面就是出现异常的一个情况,NameError是异...

  • python的中异常处理

    Python 使用被称为 异常 的特殊对象来管理程序执行期间发生的错误。每当发生让 Python 不知所措的错误时...

  • python中的异常处理

    资料来源:http://www.cnblogs.com/linhaifeng/articles/6232220.h...

  • python 中的异常处理

    何为异常 在现实生活中,我们都或多或少遇到过一些不正常的时候,这个时候就可以称为人的“异常”了,人作为一个高等生物...

网友评论

    本文标题:Python 中更优雅的异常处理方案

    本文链接:https://www.haomeiwen.com/subject/ddbruhtx.html