Python的错误捕获

我们都知道,代码发生错误时,就会中断运行。对于小段的代码,我们可以直接去把代码的错误改掉,然后重新运行。但是当代码量到达了一定程度,或者我们不想因为一个功能的出错而导致整个程序停止运行时,我们就需要一定的方法捕获和处理错误。

通常使用的方法

一般我们使用 try 和 except 来捕获和处理错误

例如

a = '123'
b = 123
try:
    print(a + b)
except Exception as e:
    print(e)

上面是一个简单的展示 try 和 except 的代码。当我们将一个字符串变量和一个整型变量拼接时就会出错,然后except捕获错误类 Exception,并用 print 将其打印出来

except打印出的错误信息

但是我们注意到,print 打印出来的错误信息是十分简略的,仅给出了错误的原因,不如平时运行出错时打印出来的信息详细

a = '123'
b = 123
print(a + b)

不使用try和except时打印出的错误信息

对于这个问题,我们可以使用 traceback 包来解决

使用 traceback 来捕获错误信息

只需要将上面的代码简单更改一下,把 print 更改为 print_exc

from traceback import print_exc

a = '123'
b = 123
try:
    print(a + b)
except Exception:
    print_exc()

可以看到此时的错误信息已经和不使用try的时候一样详细了。print_exc 能直接在标准输出端打印出详细的错误信息,如果你想获取错误信息的字符串以做更多处理,那么可以使用 format_exc 函数

from traceback import format_exc

a = '123'
b = 123
try:
    print(a + b)
except Exception:
    ErrLog = format_exc()
    print(ErrLog)

print 会自动换行,所以下面有一行空行

使用装饰器实现的错误捕获装饰器

之前在做QQ机器人的开发时,遇到的一个问题就是错误处理。因为QQ机器人有较多的功能,当添加一个新的功能进去,需要做到即使有错误出现,也不能中断程序的运行。考虑到代码的复用率较高,我决定动手写一个比较通用的错误捕获装饰器

Python 的装饰器是一个非常好用的特性,通过它不需要修改函数的源代码就可以对函数的功能进行扩展

由于我写的机器人功能的实现过程都是类似的,即功能模块仅需实现功能并生成、返回需要发送的消息,消息由消息发送模块进行发送,所以我要写的装饰器只需实现一个功能,返回函数返回的消息,或者在发生错误时返回错误信息字符串。

下面是代码

from traceback import format_exc

def TryRun(func):   #装饰器的参数是函数名
    def ReplyErr(*args, **kwargs):  #ReplyErr函数里实现需要扩展的功能,并运行函数 func
        try:
            return func(*args, **kwargs)
        except Exception:
            return '\n有错误发生\n' + format_exc()
    return ReplyErr

下面我们用它装饰一个简单的 sum 函数,这个函数会合并 a, b 两个字符串或整数或浮点数,并返回一个结果。如果 a, b 两个变量类型不一样,看看他返回什么消息

#!/usr/bin/python3
#-*- coding:utf-8 -*-

from traceback import format_exc

def TryRun(func):   #装饰器的参数是函数名
    def ReplyErr(*args, **kwargs):  #ReplyErr函数里实现需要扩展的功能,并运行函数 func
        try:
            return func(*args, **kwargs)
        except Exception:
            return '\n有错误发生\n' + format_exc()
    return ReplyErr

@TryRun
def sum(a, b):
    return a + b

if __name__ == '__main__':
    print(sum('123', '456'))    #传入两个字符串
    print(sum('123', 456))      #传入一个字符串一个整型数

现在,我就可以放心的写新功能并进行测试而不用担心错误导致程序中断了,多做的工作仅仅只需在函数前面加一行

@TryRun     #TryRun 就是我写的装饰器的名字

最后附一张机器人发送错误消息的图

发表评论

电子邮件地址不会被公开。 必填项已用*标注