二级网站建设/温州企业网站排名优化
1、主动抛出异常
当程序在发生某些状况的时候,我们希望程序能主动的抛出异常,一般我们用raise
语句,抛出异常之后,若没有try/except
的话就会扔给python
解释器去处理
基本语法:
raise SomeException,argsv
- 第一个参数
SomeException
是触发异常的名字,必须是一个字符串、类或者实例 args
描述异常信息的元组,一般我们用字符串表示异常的原因
for i in range(1,5):if i>3:raise ValueError,'i>3'else:print i# 1
# 2
# 3
# raise ValueError,'i>3'
若我们想自己去处理抛出的异常,我们需要加上try/except
。
2、简单的 try-except
用法
将可能发生异常的代码放到try语句块中,而处理异常的代码会在except语句块中实现:
try:for i in range(1,5):if i>3:raise ValueError,'i>3'else:print i
except ValueError,e:print 'catch the value error:',e
执行后,输出结果为:
# 1
# 2
# 3
# catch the value error: i>3
3、利用 assert 语句来发现问题
和其他的主流语言c/c++
一样,python
也有断言,**assert
语句是一种有条件在程序代码中触发异常,**主要是为了调试程序服务的,能快速方便的查找程序的异常,或者一些不恰当的输入。
assert
的用法如下:
assert expression, args
expression
是一个表达式args
是对条件判断的描述信息
也就是说如果表达式为假,就会触发异常,所以一般我们会把表达式写成我们认为正确的程序应该满足的条件,相当于我们代码块做的一条报警线,告诉你,正确路应该怎么走,一旦不满足正确的行为,就会响起警报 ,触发异常。
x=10
y=20
assert x==y ,'x not equal y'
>>assert x==y ,'x not equal y'
AssertionError: x not equal y
上面的代码,我们设的警戒线是x==y,这个是正确的行为,一旦x不等于y, 就会抛出异常,它在执行的过程中其实相当于执行如下代码:
x=10
y=20if __debug__ and not x==y:raise AssertionError('x not equal y')
>>
raise AssertionError('x not equal y')
AssertionError: x not equal y
__debug__
是Python
内置的系统关键字,就像None
一样,而且默认为True
,只能读不能写。
注意事项:
-
assert
虽然不错,但是不要滥用,断言是设计用来捕获用户自定义的约束, 而不是捕获程序本身的错误 -
如果程序本身的异常能够处理就不要用断言,比如列表越界啊,类型不匹配啊,除数为0这样的错误
-
还有处理用户的输入,最好用条件判断,不符合条件的时候输出错误信息就可以了
4、处理多个异常
我们可以使用三个方法来处理多个异常。
第一种方法需要把所有可能发生的异常放到一个元组里。像这样:
try:file = open(’test.txt’, ‘rb’)
except (IOError, EOFError) as e:print(“An error occurred. {}”.format(e.args[-1]))
另一种方式是对每个单独的异常在单独的except中处理。
try:file = open(’test.txt’, ‘rb’)
except IOError as e:print(“An error occurred“)raise e
except EOFError as e:print((“An EOF error occurred"))raise e
最后一种方式会捕获所有异常:
try:file = open(’test.txt’, ‘rb’)
except Exception as e:# 打印一些异常日志raise e
5、finnaly
从句
包裹在finnaly
从句中的代码不管异常是否出发都会被执行。这可以被用来在脚本执行之后做清理工作。
try:file = open(’test.txt’, ‘rb’)
except IOError as e:print(“An error occurred“)
finnaly:print(“This would be printed whether or not an exception occurred")
6、tracebac
模块
我们发现普通的打印异常只有很少量的信息(通常是异常的value值),这种情况下我们很难定位在哪块代码出的问题,以及如何出现这种异常。那么到底要如何打印更加详细的信息呢?traceback
模块可以帮你。
Python 程序的traceback
信息均来源于一个叫做traceback object
的对象,而这个traceback object
通常是通过函数sys.exc_info()
来获取的,先来看一个例子:
# -*- coding: utf-8 -*-
import sysdef func1():raise NameError("--func1 exception")def main():try:func1()except Exception as e:exc_type, exc_value, exc_traceback_obj = sys.exc_info()print("exc_type: %s" % exc_type)print("exc_value: %s" % exc_value)print("exc_traceback_obj: %s" % exc_traceback_obj)if __name__ == '__main__':main()
输出结果如下:
exc_type: <type 'exceptions.NameError'>
exc_value: --func1 exception--
exc_traceback_obj: <traceback object at 0x7faddf5d93b0>
通过以上示例我们可以看出,sys.exc_info()
获取了当前处理的exception
的相关信息,并返回一个元组。
- 元组的第一个数据是异常的类型(示例是
NameError
类型), - 第二个返回值是异常的
value
值, - 第三个就是我们要的
traceback object
.
有了traceback object
我们就可以通过traceback module
来打印和格式化traceback
的相关信息,下面我们就来看下traceback module
的相关函数。
Python的traceback module
提供一整套接口用于提取、格式化和打印Python程序的stack traces
信息,下面我们通过例子来详细了解下这些接口:
print_tb
接口
# -*- coding: utf-8 -*-
import sys
import tracebackdef func1():raise NameError("--func1 exception")def main():try:func1()except Exception as e:exc_type, exc_value, exc_traceback_obj = sys.exc_info()traceback.print_tb(exc_traceback_obj)if __name__ == '__main__':main()
输出结果:
File "/Users/didi/Desktop/python/traceback/traceback_print_tb.py", line 13, in mainfunc1()File "/Users/didi/Desktop/python/traceback/traceback_print_tb.py", line 8, in func1raise NameError("--func1 exception")
这里我们可以发现打印的异常信息更加详细了,下面我们了解下print_tb
的详细信息:
traceback.print_tb(tb[, limit[, file]])
tb
: 这个就是traceback object
, 是我们通过sys.exc_info
获取到的limit
: 这个是限制stack trace
层级的,如果不设或者为None
,就会打印所有层级的stack trace
file
: 这个是设置打印的输出流的,可以为文件,也可以是stdout之类的file-like object
。如果不设或为None
,则输出到sys.stderr
。
print_exception
接口
# -*- coding: utf-8 -*-
import sys
import tracebackdef func1():raise NameError("--func1 exception")def main():try:func1()except Exception as e:exc_type, exc_value, exc_traceback_obj = sys.exc_info()traceback.print_exception(exc_type, exc_value, exc_traceback_obj, limit=2, file=sys.stdout)if __name__ == '__main__':main()
输出结果:
Traceback (most recent call last):File "/Users/didi/Desktop/python/traceback/traceback_print_exception.py", line 13, in mainfunc1()File "/Users/didi/Desktop/python/traceback/traceback_print_exception.py", line 8, in func1raise NameError("--func1 exception")
NameError: --func1 exception
看下定义:
traceback.print_exception(etype, value, tb[, limit[, file]])
- 跟
print_tb
相比多了两个参数etype
和value
,分别是exception type
和exception value
,加上tb(traceback object)
,正好是sys.exc_info()
返回的三个值 - 另外,与
print_tb
相比,打印信息多了开头的"Traceback (most...)"
信息以及最后一行的异常类型和value
信息 - 还有一个不同是当异常为
SyntaxError
时,会有"^"
来指示语法错误的位置
print_exc
接口
print_exc
是简化版的print_exception
, 由于exception type
, value
和traceback object
都可以通过sys.exc_info()
获取,因此print_exc()
就自动执行exc_info()
来帮助获取这三个参数了,也因此这个函数是我们的程序中最常用的,因为它足够简单
# -*- coding: utf-8 -*-
import sys
import tracebackdef func1():raise NameError("--func1 exception")def func2():func1()def main():try:func2()except Exception as e:traceback.print_exc(limit=1, file=sys.stdout)if __name__ == '__main__':main()
输出结果为:
Traceback (most recent call last):File "/Users/didi/Desktop/python/traceback/traceback_print_exc.py", line 17, in mainfunc2()
NameError: --func1 exception
定义如下:
traceback.print_exc([limit[, file]])
- 只有两个参数,够简单
format_exc
接口
# -*- coding: utf-8 -*-import sys
import traceback
import logging
logger = logging.getLogger("traceback_test")def func1():raise NameError("--func exception")def func2():func1()def main():try:func2()except Exception as e:logger.error(traceback.format_exc(limit=1))if __name__ == '__main__':main()
从这个例子可以看出有时候我们想得到的是一个字符串,比如我们想通过logger将异常记录在log
里,这个时候就需要format_exc
了,这个也是最常用的一个函数,它跟print_exc
用法相同,只是不直接打印而是返回了字符串。