1.捕获错误的目的只是记录一下,便于后续追踪,但是,由于当前函数不知道应该如何处理该错误,所以,最恰当的方式是继续往上抛,让顶层调用者去处理。
看下面的代码:
def foo(s):
n = int(s)
return 10/n
def bar(s):
try:
return foo(s)*2
except StandardError,e:
print 'Error'
raise
if __name__ == "__main__":
bar('0')
在bar()函数中,我们已经明明已经捕获了错误,但是,打印一个“Error”之后,又把错误通过raise语句抛出。
raise语句如果不带参数,就会把当前错误原样抛出。此外,在except中raise一个Error,还可以把一种类型的错误转化成另一种类型:
try:
10/0
except ZeroDivisionError:
raise ValueError("input error")
note: 这样转换错误类型应该符合转换逻辑,但是绝不应该把一个IOError转换成不相干的ValueError.
2. finally 的作用
fianlly里面大多时候都是用来释放资源的,比如关闭文件,关闭数据库的连接等。
3. logging 记录错误
如果不捕获错误,自然可以让Python解释器来打印出错误堆栈,但程序也被结束了。既然我们能捕获错误,就可以把错误堆栈打印出来,然后分析错误原因,同时,让程序继续执行下去。
Python内置的logging模块可以非常容易的记录错误信息:
#err.py
import logging
def foo(s):
return 10/int(s)
def bar(s):
return foo(s)*2
if __name__ == "__main__":
try:
bar("0")
except StandardError, e:
logging.exception(e)
同样是出错,但是程序打印完错误信息后继续执行(在屏幕上),并正常退出:
$ python err.py
ERROR:root:integer division or modulo by zero
Traceback (most recent call last):
File "err.py", line 12, in main
bar('0')
File "err.py", line 8, in bar
return foo(s) * 2
File "err.py", line 5, in foo
return 10 / int(s)
ZeroDivisionError: integer division or modulo by zero
4.logging 日志文件-此部分出自DK’s Blog,感谢他的总结
但是如果我们希望将错误写入日志中,方便以后排查错误,通过配置也可以将错误写入到日志文件当中:
4.1.简单的将日志打印到屏幕
import logging
logging.debug("This is debug message")
logging.info("This is info message")
logging.warning("This is warning message")
#WARNING:root:This is warning message
默认情况下,logging将日志打印到屏幕,日志级别为WARNING;
日志级别大小关系为:CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET,当然也可以自己定义日志级别。
4.2 通过logging.basicConfig函数对日志的输出格式及方式做相关配置
import logging
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
datefmt='%a, %d %b %Y %H:%M:%S',
filename='myapp.log',
filemode='w')
logging.debug('This is debug message')
logging.info('This is info message')
logging.warning('This is warning message')