本系列博文基于廖雪峰老师的官网Python教程,笔者在大学期间已经阅读过廖老师的Python教程,教程相当不错,官网链接: 廖雪峰官方网站.请需要系统学习Python的小伙伴到廖老师官网学习,笔者的编程环境是Anaconda+Pycharm,Python版本:Python3.
1.错误处理
# 错误处理:在程序运行过程中,如果发生了错误,可以事先约定返回一个错误代码;
# 这样可以知道是否有错,及出错的原因;
# Python中的try...except...finally...错误处理机制
# 实例1:
"""
下面代码执行过程:
1.认为某段代码可能会出错,用try来运行这段代码;
2.如果执行出错,则后续代码不会继续执行,直接跳到错误处理代码,即except语句块;
3.执行完except后,如果有finally语句块,则执行finally语句块,执行完毕;
"""
try:
print("This is try...")
r = 10 / 0
print("result:", r) # 该语句不会被执行
except ZeroDivisionError as e:
print("except:", e)
finally:
print("This is finally...")
print("The End.")
# 结果输出:
This is try...
except: division by zero
This is finally...
The End.
# 如果发生不同类型的错误,应该由不同的except语句块处理
try:
print("Try start...")
r = 10 / int("a")
print("Result:", r)
except ValueError as e:
print("ValueError:", e)
except ZeroDivisionError as e:
print("ZeroDivisionError:", e)
finally:
print("This is finally.")
print("The End.")
# 结果输出:
Try start...
ValueError: invalid literal for int() with base 10: 'a'
This is finally.
The End.
# 如果没有错误发生,可以在except语句块后加一个else
try:
print("Try start...")
r = 10 / int("2")
print("Result:", r)
except ValueError as e:
print("ValueError:", e)
except ZeroDivisionError as e:
print("ZeroDivisionError:", e)
else:
print("No Error.")
finally:
print("This is finally...")
print("The End.")
# 结果输出:
Try start...
Result: 5.0
No Error.
This is finally...
The End.
# 调用栈
# 如果错误没有被捕获,则会一直往上抛,最后被Python解释器捕获,打印一个错误信息,程序退出
def foo(s):
return 10 / int(s)
def bar(s):
return foo(s) * 2
def main():
bar("0")
main()
"""
关于抛出的错误信息的解读:
1.Traceback (most recent call last):错误的跟踪信息;
2.<ipython-input-9-827ff6360928> in <module>
10 bar("0")
11
---> 12 main()
调用main()出错,在代码文件的12行,错误的原因在第10行
3.<ipython-input-9-827ff6360928> in main()
8
9 def main():
---> 10 bar("0")
调用bar("0")出错,在代码文件的第10行,错误的原因在第7行
4.<ipython-input-10-2a5eb4c1a077> in bar(s)
5
6 def bar(s):
----> 7 return foo(s) * 2
8
9 def main():
5. 3 def foo(s):
----> 4 return 10 / int(s)
5
6 def bar(s):
原因是:return 10 / int(s)这个语句出错,是错误产生的源头
"""
# 结果输出:
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
<ipython-input-10-2a5eb4c1a077> in <module>
10 bar("0")
11
---> 12 main()
13
14 """
<ipython-input-10-2a5eb4c1a077> in main()
8
9 def main():
---> 10 bar("0")
11
12 main()
<ipython-input-10-2a5eb4c1a077> in bar(s)
5
6 def bar(s):
----> 7 return foo(s) * 2
8
9 def main():
<ipython-input-10-2a5eb4c1a077> in foo(s)
2 # 如果错误没有被捕获,则会一直往上抛,最后被Python解释器捕获,打印一个错误信息,程序退出
3 def foo(s):
----> 4 return 10 / int(s)
5
6 def bar(s):
ZeroDivisionError: division by zero
# 记录错误
# 捕获错误,把错误堆栈打印,分析错误原因,让程序继续执行下去
import logging
def foo(s):
return 10 / int(s)
def bar(s):
return foo(s) * 2
def main():
try:
bar("0")
except Exception as e:
logging.exception(e)
main()
print("The End.")
# 结果输出:
ERROR:root:division by zero
Traceback (most recent call last):
File "<ipython-input-11-20576a90bb23>", line 13, in main
bar("0")
File "<ipython-input-11-20576a90bb23>", line 9, in bar
return foo(s) * 2
File "<ipython-input-11-20576a90bb23>", line 6, in foo
return 10 / int(s)
ZeroDivisionError: division by zero
The End.
# 抛出错误
class FooError(ValueError):
pass
def foo(s):
n = int(s)
if n == 0:
raise FooError("invalid value:%s" %s)
return 10 / n
foo("0")
---------------------------------------------------------------------------
FooError Traceback (most recent call last)
<ipython-input-12-984c6a65ff3f> in <module>
9 return 10 / n
10
---> 11 foo("0")
<ipython-input-12-984c6a65ff3f> in foo(s)
6 n = int(s)
7 if n == 0:
----> 8 raise FooError("invalid value:%s" %s)
9 return 10 / n
10
FooError: invalid value:0
# 常用的错误处理方式
def foo(s):
n = int(s)
if n == 0:
raise ValueError("Invalid Value:%s" % s)
return 10 / n
def bar():
try:
foo("0")
except ValueError as e:
print("ValueError!")
raise
bar()
# 结果输出:
ValueError!
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-13-ed53b99ac832> in <module>
14
15
---> 16 bar()
<ipython-input-13-ed53b99ac832> in bar()
8 def bar():
9 try:
---> 10 foo("0")
11 except ValueError as e:
12 print("ValueError!")
<ipython-input-13-ed53b99ac832> in foo(s)
3 n = int(s)
4 if n == 0:
----> 5 raise ValueError("Invalid Value:%s" % s)
6 return 10 / n
7
ValueError: Invalid Value:0
2.调试
# 断言:assert
def foo(s):
n = int(s)
assert n != 0, "n is zero!"
return 10 / n
def main():
foo("0")
main()
# 结果输出:
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
<ipython-input-14-409f5b6bb04f> in <module>
8 foo("0")
9
---> 10 main()
<ipython-input-14-409f5b6bb04f> in main()
6
7 def main():
----> 8 foo("0")
9
10 main()
<ipython-input-14-409f5b6bb04f> in foo(s)
2 def foo(s):
3 n = int(s)
----> 4 assert n != 0, "n is zero!"
5 return 10 / n
6
AssertionError: n is zero!
# logging:不会抛出错误,可以输出到文件
import logging
# 指定记录信息的级别:debug,info,warning,error等几个级别
logging.basicConfig(level = logging.INFO)
s = "0"
n = int(s)
logging.info("n = %d" % n)
print(10 / n)
# 结果输出:
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
<ipython-input-20-8be18d57ae14> in <module>
6 n = int(s)
7 logging.info("n = %d" % n)
----> 8 print(10 / n)
ZeroDivisionError: division by zero
3.单元测试
# 单元测试:对一个模块,一个函数,或一个类进行正确性检验的测试;
"""
实例:
对函数abs()编写测试用例:
a.输入正数,如:1、1.2、0.99,期待返回值与输入相同;
b.输入负数,如:-1、-1.2、-0.99,期待返回值与输入相反;
c.输入0,期待返回0;
d.输入非数值类型,如:None、[]、{},期待抛出TypeError;
把上述测试用例放到一个测试模块里,就是一个完整的单元测试;
"""
# mydict.py文件
class Dict(dict):
def __init__(self, **kw):
super().__init__(**kw)
def __getattr__(self, key):
try:
return self[key]
except KeyError:
raise AttributeError(r"'Dict' object has no attribute '%s'" % key)
def __setattr__(self, key, value):
self[key] = value
# mydict_test.py文件
import unittest
from mydict import Dict
class TestDict(unittest.TestCase):
def test_init(self):
d = Dict(a=1, b='test')
self.assertEqual(d.a, 1)
self.assertEqual(d.b, 'test')
self.assertTrue(isinstance(d, dict))
def test_key(self):
d = Dict()
d['key'] = 'value'
self.assertEqual(d.key, 'value')
def test_attr(self):
d = Dict()
d.key = 'value'
self.assertTrue('key' in d)
self.assertEqual(d['key'], 'value')
def test_keyerror(self):
d = Dict()
with self.assertRaises(KeyError):
value = d['empty']
def test_attrerror(self):
d = Dict()
with self.assertRaises(AttributeError):
value = d.empty
if __name__ == "__main__":
unittest.main()
# 在交互环境下,运行python mydict_test.py
4.文档测试
# mydict2.py
class Dict(dict):
'''
Simple dict but also support access as x.y style.
>>> d1 = Dict()
>>> d1['x'] = 100
>>> d1.x
100
>>> d1.y = 200
>>> d1['y']
200
>>> d2 = Dict(a=1, b=2, c='3')
>>> d2.c
'3'
>>> d2['empty']
Traceback (most recent call last):
...
KeyError: 'empty'
>>> d2.empty
Traceback (most recent call last):
...
AttributeError: 'Dict' object has no attribute 'empty'
'''
def __init__(self, **kw):
super(Dict, self).__init__(**kw)
def __getattr__(self, key):
try:
return self[key]
except KeyError:
raise AttributeError(r"'Dict' object has no attribute '%s'" % key)
def __setattr__(self, key, value):
self[key] = value
if __name__=='__main__':
import doctest
doctest.testmod()
# 在交互环境输入:python mydict2.py