用户名  找回密码
 立即注册
注册 登录
×
热搜: 活动 交友 discuz
查看: 79|回复: 1

第八章.Python编程:异常与调试

[复制链接]

2

主题

2

帖子

6

积分

新手上路

Rank: 1

积分
6
发表于 2023-1-12 15:15:18 | 显示全部楼层 |阅读模式
我年纪轻轻就学会了Python编程
本章目录


  • 异常
  • 调试
  • 单元调试
  • 文档调试
一、异常

在程序的运行过程中,发生异常或者错误是非常正常的,一般来说,编程语言都会设定一些特有的异常和自定义异常,我们需要捕捉它们,
这样就可以知道是否有错,出错的原因是什么,以及如果出现错误我们应该怎么修复跳过等,甚至我们需要在特定的情况下需要引发一些异常。
Python常见的异常有以下几种:

  • AssertionError:断言语句失败(assert 后的条件为假)
  • AttributeError:访问的对象属性不存在
  • ImportError:无法导入模块或者对象,主要是路径有误或名称错误
  • IndentationError:代码没有正确对齐,主要是缩进错误
  • IndexError:下标索引超出序列范围
  • IOError:输入/输出异常,主要是无法打开文件
  • KeyError:访问字典里不存在的键
  • NameError:访问一个未声明的变量
  • OverflowError:数值运算超出最大限制
  • SyntaxError:python语法错误
  • TabError:Tab和空格混用
  • TypeError:不同类型数据之间的无效操作(传入对象类型与要求的不符合)
  • ValueError:传入无效的值,即使值的类型是正确的
  • ZeroDivisionError:除法运算中除数0 或者 取模运算中模数为0
  • Exception:自定义异常
一旦程序发生异常,表明该程序在执行时出现了非正常的情况,无法再执行下去。默认情况下,程序会终止退出。
捕获异常

Python提供以下关键语句来捕捉异常:
try:
    处理代码块

except 异常:         ### 不写异常表示捕捉所有异常
    发生异常的代码块
a = 1
b = '2'
c = a + b



output:

    ---------------------------------------------------------------------------

    TypeError                                 Traceback (most recent call last)

    ~\AppData\Local\Temp/ipykernel_9612/2197615168.py in <module>
          1 a = 1
          2 b = '2'
    ----> 3 c = a + b


    TypeError: unsupported operand type(s) for +: 'int' and 'str'
try:
    a = 1
    b = '2'
    c = a+b
except:
    c = 3

print(c)



output:

    3
### 捕捉特定异常,这样就可以方便我们差错

try:
    a = 1
    b = '2'
    c = a+b
except TypeError:
    c = 3

print(c)



output:

    3加上关键字else表示不发生异常运行

try:
    处理代码块

except 异常:         ### 不写异常表示捕捉所有异常
    发生异常的代码块

else:
    不发生异常处理代码块else一般可以不写可以通过缩进来进行后面的代码块区分
try:
    a = 1
    b = '2'
    c = a+b
except TypeError:
    c = 3
else:
    print(c)
try:
    a = 1
    b = 2
    c = a+b
except TypeError:
    c = 3
else:
    print(c)



output:

    3加上换剪子finally表示无论有没有异常都会执行的代码块

try:
    处理代码块

except 异常:         ### 不写异常表示捕捉所有异常
    发生异常的代码块

else:
    不发生异常处理代码块

finally:
    无论有么有异常都执行的代码块
try:
    a = 1
    b = '2'
    c = a+b
except TypeError:
    c = 3
else:
    c = 4
finally:
    print(c)



output:

    3泛华异常

很多情况下,我们根本不知道会发生什么具体类型的异常,这时候我们使用关键字:Exception表示所有异常,并且提供关键字:as,可以重命名该异常
try:
    处理代码块

except Exception as e:         ### 不写异常表示捕捉所有异常
    print(e)
try:
    a = 1
    b = '2'
    c = a+b
except Exception as e:
    print(f'异常信息:{e}')



output:

    异常信息:unsupported operand type(s) for +: 'int' and 'str'更详细的捕捉异常

捕捉异常的本质是为了让我们发现并修改错误,有时候代码太多,调用太繁琐不是很容易发现,这时候需要具体到哪一行代码发生了错误,
Python提供内置模块:traceback来详细的打印异常,常用方法有:

  • traceback.print_exc():打印具体异常信息
  • traceback.format_exc():返回异常信息字符串方便二次处理
import traceback

try:
    a = 1
    b = '2'
    c = a+b
except:
    traceback.print_exc()




output:

    Traceback (most recent call last):
      File "C:\Users\DELL\AppData\Local\Temp/ipykernel_9612/3288308381.py", line 6, in <module>
        c = a+b
    TypeError: unsupported operand type(s) for +: 'int' and 'str'
try:
    a = 1
    b = '2'
    c = a+b
except:
    info = traceback.format_exc()

print(info)



output:

    Traceback (most recent call last):
      File "C:\Users\DELL\AppData\Local\Temp/ipykernel_9612/511410514.py", line 4, in <module>
        c = a+b
    TypeError: unsupported operand type(s) for +: 'int' and 'str'自定义引发异常

Python提供关键字:raise,搭配:Exception,用来引发自定义异常
raise Exception('异常字符串')
a = 1
raise Exception('这是一个自定义的异常')



output:

    ---------------------------------------------------------------------------

    Exception                                 Traceback (most recent call last)

    ~\AppData\Local\Temp/ipykernel_9612/1205731023.py in <module>
          1 a = 1
    ----> 2 raise Exception('这是一个自定义的异常')


    Exception: 这是一个自定义的异常二、调试

一般来说,程序一次性写完并正常运行的概率非常小,经常发生某些bug,总会有各种bug需要修复,这可能就是导致脱发的根本原因,
有些bug看看报错信息就知道怎么解决,有些bug很复杂,我们需要知道哪里出了错,这时候就需要一套完整的调试程序修复bug
最常用的方法有:

  • try...except:...:捕捉异常信息
  • print():简单粗暴打印各种变量信息
  • assert:断言辅助查看
使用:print

def sums(a,b):
    return a+b

sums(1,'2')



output:

    ---------------------------------------------------------------------------

    TypeError                                 Traceback (most recent call last)

    ~\AppData\Local\Temp/ipykernel_9612/440557491.py in <module>
          2     return a+b
          3
    ----> 4 sums(1,'2')


    ~\AppData\Local\Temp/ipykernel_9612/440557491.py in sums(a, b)
          1 def sums(a,b):
    ----> 2     return a+b
          3
          4 sums(1,'2')


    TypeError: unsupported operand type(s) for +: 'int' and 'str'
def sums(a,b):

    print(f'a: {type(a)}')
    print(f'b: {type(b)}')

    return a+b

sums(1,'2')



output:

    a: <class 'int'>
    b: <class 'str'>



    ---------------------------------------------------------------------------

    TypeError                                 Traceback (most recent call last)

    ~\AppData\Local\Temp/ipykernel_9612/2972384813.py in <module>
          6     return a+b
          7
    ----> 8 sums(1,'2')


    ~\AppData\Local\Temp/ipykernel_9612/2972384813.py in sums(a, b)
          4     print(f'b: {type(b)}')
          5
    ----> 6     return a+b
          7
          8 sums(1,'2')


    TypeError: unsupported operand type(s) for +: 'int' and 'str'使用断言:assert

assert isinstance(b,int)

def sums(a,b):

    assert isinstance(a,int)
    assert isinstance(b,int)

    return a+b

sums(1,'2')



output:

    ---------------------------------------------------------------------------

    AssertionError                            Traceback (most recent call last)

    ~\AppData\Local\Temp/ipykernel_9612/2712414290.py in <module>
    ----> 1 assert isinstance(b,int)
          2
          3 def sums(a,b):
          4
          5     assert isinstance(a,int)


    AssertionError:适当的加上print和assert可以方便修复bug,但一定要记住,程序正式上线一定要注释掉这些地方,因为它们非常影响运行速度
三、单元调试

上述调试其实只是对一句代码进行调试,Python是一个函数式编程,有很多的函数,类,第三方模块等需要测试工作,这时候就需要单元调试
比如Python有个内置函数:abs(),正常返回如下:

  • 输入正数:返回和输入相同
  • 输入负数:返回和输入相反
  • 输入0:返回0
  • 输入非数值类型,如:None、str等,输出异常:TypeError
如果把这个函数的四个用例放在一个测试模块,那就是一套完整的单元调试,
假如通过单元调试,则说明函数正常工作;
假如不通过单元调试,则说明函数存在bug。
Python提供内置模块:unittest进行单元调试
# %load ./examples/testing.py
import unittest

class TestABS(unittest.TestCase):

    def test_example1(self):
        self.assertEqual(abs(1),1)

    def test_example2(self):
        self.assertEqual(abs(-1),1)

    def test_example3(self):
        self.assertEqual(abs(0),0)

    def test_example4(self):
        a = '1'
        with self.assertRaises(TypeError):
            abs(a)

if __name__ == '__main__':
    unittest.main()
%%cmd
python ./examples/testing1.py



output:

    Microsoft Windows [版本 10.0.22598.200]
    (c) Microsoft Corporation。保留所有权利。

    E:\notebook\B站\花卷学Python\8. Python编程:异常与调试>python ./examples/testing1.py

    E:\notebook\B站\花卷学Python\8. Python编程:异常与调试>

    ..
    ----------------------------------------------------------------------
    Ran 2 tests in 0.000s

    OK比如我们调试一个自定义的类

# %load ./examples/testing1.py
class Student(object):
    def __init__(self, name: str = '', score: int = 0):
        self.name = name
        self.score = score

    def get_grade(self):
        if self.score > 80:
            return '优秀'
        else:
            return '良好'




import unittest

class TestABS(unittest.TestCase):

    def test_greater_80(self):
        a = Student('a',90)
        self.assertEqual(a.get_grade(),'优秀')

    def test_less_80(self):
        a = Student('a',70)
        self.assertEqual(a.get_grade(),'良好')


if __name__ == '__main__':
    unittest.main()
%%cmd
python ./examples/testing1.py



output:

    Microsoft Windows [版本 10.0.22598.200]
    (c) Microsoft Corporation。保留所有权利。

    E:\notebook\B站\花卷学Python\8. Python编程:异常与调试>python ./examples/testing1.py

    E:\notebook\B站\花卷学Python\8. Python编程:异常与调试>

    ..
    ----------------------------------------------------------------------
    Ran 2 tests in 0.000s

    OK四、文档调试

假如你经常看Python的源码,会发现很多函数或者类都提供了文档,里面包含该函数或者类的交互式运行方式,
一般来说,当我们使用一个陌生的函数或者类,看一下文档粘贴复制就可以直接使用它了,
比如:
def myabs(a):
    """
    绝对值函数

    Example:

    >>> myabs(1)
    1

    >>> myabs(-1)
    1

    >>> myabs(0)
    0

    >>> myabs('1')
    TypeError Traceback (most recent call last)
        ...
    TypeError: bad operand type for abs(): 'str'
    """
    res = a if a >= 0 else -a
    return res
print(myabs.__doc__)



output:

        绝对值函数

        Example:

        >>> myabs(1)
        1

        >>> myabs(-1)
        1

        >>> myabs(0)
        0

        >>> myabs('1')
        TypeError Traceback (most recent call last)
            ...
        TypeError: bad operand type for abs(): 'str'该文档非常明确的告诉你:myabs函数怎么运行
Python提供内置模块:doctest直接提取文档并执行测试
doctest严格按照Python交互式命令行的输入和输出来判断测试结果是否正确。只有测试异常的时候,可以用...表示中间一大段烦人的输出。
比如我们测试一下我们的:myabs函数
# %load ./examples/testing2.py
def myabs(a):
    """
    绝对值函数

    Example:

    >>> myabs(1)
    1

    >>> myabs(-1)
    1

    >>> myabs(0)
    0

    >>> myabs('1')
    TypeError Traceback (most recent call last)
        ...
    TypeError: bad operand type for abs(): 'str'
    """
    res = a if a >= 0 else -a
    return res




if __name__ == "__main__":
    import doctest
    doctest.testmod()
%%cmd
python ./examples/testing2.py



output:

    Microsoft Windows [版本 10.0.22598.200]
    (c) Microsoft Corporation。保留所有权利。

    E:\notebook\B站\花卷学Python\8. Python编程:异常与调试>python ./examples/testing2.py
    **********************************************************************
    File "E:\notebook\B站\花卷学Python\8. Python编程:异常与调试\examples\testing2.py", line 16, in __main__.myabs
    Failed example:
        myabs('1')
    Exception raised:
        Traceback (most recent call last):
          File "D:\anaconda\lib\doctest.py", line 1336, in __run
            exec(compile(example.source, filename, "single",
          File "<doctest __main__.myabs[3]>", line 1, in <module>
            myabs('1')
          File "E:\notebook\B站\花卷学Python\8. Python编程:异常与调试\examples\testing2.py", line 21, in myabs
            res = a if a >= 0 else -a
        TypeError: '>=' not supported between instances of 'str' and 'int'
    **********************************************************************
    1 items had failures:
       1 of   4 in __main__.myabs
    ***Test Failed*** 1 failures.

    E:\notebook\B站\花卷学Python\8. Python编程:异常与调试>赞赏

读后若有收获,可以微信请作者喝咖啡:

回复

举报

0

主题

2

帖子

4

积分

新手上路

Rank: 1

积分
4
发表于 6 天前 | 显示全部楼层
嘘,低调。
回复

举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋| 黑客通

GMT+8, 2025-4-7 20:29 , Processed in 0.094138 second(s), 22 queries .

Powered by Discuz! X3.4

Copyright © 2020, LianLian.

快速回复 返回顶部 返回列表