赞
踩
我有一组Python脚本,它们以嵌套的方式调用函数。对于这些函数中的每一个,我都有一个try,除了语句来捕获每个异常并打印它们。我想发送一封电子邮件警报,其中包含执行期间遇到的完整异常序列。例:
import sys
def SendAlert(ErrorMessage):
try:
#send email alert with error message
#[...]
except:
print(str(sys.exc_info()))
return(sys.exc_info())
def ParentFunction():
try:
#call ChildFunction
ChildResult = ChildFunction()
#do stuff with ChildResult
#[...]
return ParentResult
except:
ErrorMessage = str(sys.exc_info())
print(ErrorMessage)
SendAlert(ErrorMessage)
def ChildFunction():
try:
#do stuff
#[...]
return ChildResult
except:
print(str(sys.exc_info()))
return(sys.exc_info())
#main
if __name__ == '__main__':
Result = ParentFunction()
如果ChildFunction中出现错误,上面的代码将表现如下,这是最嵌套的函数:
ChildFunction遇到异常,它将打印并返回
错误消息到ParentFunction
ParentFunction将失败,因为ChildResult包含错误消息而不是有效值
ParentFunction将触发和异常,并在电子邮件警报中发送自己的错误消息
除了来自ParentFunction的错误消息之外,我希望电子邮件警报包含来自ChildFunction的错误消息。请注意,我想避免在ParentFunction的except语句中将ChildResult变量传递给SendAlert函数,因为在现实生活中我的程序有很多嵌套函数,这意味着将每个函数的结果变量传递给除了声明。
你会如何实现这一目标?有没有办法访问整个程序触发的完整错误序列?
谢谢
如何重新提高例外?
你什么意思?
为什么不使用try ... except Exception as error?
谢谢Chiheb,这也是Azat在下面推荐的。 我会尝试。
你不需要返回用sys.exc_info获得的异常:我们可以重新提升它
try:
# do stuff
# FIXME: we should avoid catching too broad exception
except Exception as err:
# do stuff with exception
raise err
所以你的例子看起来像
def SendAlert(ErrorMessage):
try:
# send email alert with error message
# [...]
pass
# what kind of exceptions may occur while sending email?
except Exception as err:
print(err)
raise err
def ParentFunction():
try:
# call ChildFunction
ChildResult = ChildFunction()
ParentResult = ChildResult
# do stuff with ChildResult
# [...]
return ParentResult
# FIXME: we should avoid catching too broad exception
except Exception as err:
ErrorMessage = str(err)
# why do we need to print again?
print(ErrorMessage)
SendAlert(ErrorMessage)
def ChildFunction():
try:
ChildResult = 0
# do stuff
# [...]
# let's raise `ZeroDivisionError`
ChildResult /= 0
return ChildResult
# FIXME: we should avoid catching too broad exception
except Exception as err:
print(err)
raise err
# main
if __name__ == '__main__':
Result = ParentFunction()
进一步改进
对于打印完整错误回溯,我们可以使用logging模块
import logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
def SendAlert(ErrorMessage):
try:
# send email alert with error message
# [...]
pass
# what kind of exceptions may occur while sending email?
except Exception as err:
logger.exception('Error while sending email')
# we're not receiving values from this function
raise err
def ParentFunction():
try:
# call ChildFunction
ChildResult = ChildFunction()
ParentResult = ChildResult
# do stuff with ChildResult
# [...]
return ParentResult
# FIXME: we should avoid catching too broad exception
except Exception as err:
# this will log full error traceback
# including `ChildFunction`
logger.exception('Error in ParentFunction')
ErrorMessage = str(err)
SendAlert(ErrorMessage)
def ChildFunction():
ChildResult = 0
# do stuff
# [...]
# e. g. let's raise `ZeroDivisionError`
ChildResult /= 0
return ChildResult
# main
if __name__ == '__main__':
Result = ParentFunction()
它只是冰山一角,logging很棒,你绝对应该使用它。
进一步阅读
记录HOWTO,
SMTPHandler,用于通过SMTP发送电子邮件错误
感谢您的进一步改进,我刚刚测试了上面的脚本。一个问题,因为脚本正在重新提升并使用完整的异常序列记录ParentFunction中的异常,也许我不需要在ChildFunction中记录它?否则,日志会因为大量冗余而变得非常垃圾,因此可读性较差。你怎么看?
@ Alexis.Rolland:ofc你不应该两次记录相同的异常,所以随意删除ChildFunction内的记录
好的,对不起,如果这听起来是一个愚蠢的问题,但如果我自己删除了试试...除了来自ChildFunction的条款怎么办? ParentFunction仍然可以进行日志记录吗? (现在无法测试我在手机上)
我的意思是当然记录完整的异常序列...... :)
@ Alexis.Rolland:是的,它会起作用
@ Alexis.Rolland:完成答案,有什么可以改进的吗?
您还可以创建一个custom exception,它可以获取描述性错误消息并将其返回。
这是一个简单的例子,您可以修改它并将其实现到您的代码中,直到它满足您的需求:
class MyCustomError(Exception):
def __init__(self, err):
Exception.__init__(self)
self.error = err
def __str__(self):
return"%r" % self.error
a = 1
try:
if a != 0:
raise MyCustomError("This is an Error!")
except MyCustomError as err:
print(err)
输出:
'This is an Error!'
谢谢Chiheb,我对课程很陌生,请你详细说明它在这里的作用及其好处?
使用这种自定义异常(类),您可以轻松地跟踪代码中的错误,还可以在类中添加其他重复代码。例如,当存在异常时,您希望将错误记录到文件中,然后继续处理其余代码。或者,当存在异常时,您希望在执行其余代码之前调用方法/函数。没有限制......这也是将异常分类成组的一个方便的技巧。等等...
有关更多信息,请参见此处。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。