Python3学习17--错误、调试和测试

本系列博文基于廖雪峰老师的官网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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FUXI_Willard

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值