python基础-异常处理 异常值处理python

   2023-02-09 学习力0
核心提示:python异常处理机制1.异常与异常处理  异常就是程序中的错误,正常情况下程序是自上而下逐行执行的,当遇到异常时,就会报错退出执行;  异常处理就是在程序中可能出错的地方进行提前预捕获,并将异常部分的程序进行修正使得程序正常执行。 2.异常的语法

1.异常与异常处理

  异常就是程序中的错误,正常情况下程序是自上而下逐行执行的,当遇到异常时,就会报错退出执行;

  异常处理就是在程序中可能出错的地方进行提前预捕获,并将异常部分的程序进行修正使得程序正常执行。

 

2.异常的语法

  利用try ... except ... 关键字

# 以字符串的upper方法为例

def new_upper(str_data):
    new_str = str_data.upper()
    return new_str

# 输入正常的字符串,程序执行正常,返回结果正常
new_str = new_upper('test_str')
print(new_str)
'''
TEST_STR
'''

# 输入非字符串类型,程序会报错
new_str2 = new_upper(1)
print(new_str2)
'''
Traceback (most recent call last):
  File "D:\python_exercise\try_except.py", line 15, in <module>
    new_str2 = new_upper(1)
  File "D:\python_exercise\try_except.py", line 6, in new_upper
    new_str = str_data.upper()
AttributeError: 'int' object has no attribute 'upper'
'''
# 接上,此时可以通过try...except...提前捕获异常

def new_upper(str_data):
    new_str = 'init_value'
    try:
        new_str = str_data.upper()
        print('try中代码继续执行')
    except:
        print('传入的字符串参数可能有误,请检查!')
    print('整个方法继续执行')
    return new_str


# 传入的数据正确时
new_str = new_upper('test_str')
print(new_str)
# try模块中没有异常出现,则不会执行except模块中代码;程序自上而下正常执行
'''
try中代码继续执行
整个方法继续执行
TEST_STR
'''
# 传入的数据出错时,会立即执行except模块中代码,且try中后续代码不再执行,整个方法的后续代码会继续执行
new_str = new_upper(1)
print(new_str)
'''
传入的字符串参数可能有误,请检查!
整个方法继续执行
init_value
'''

 

3.保存并处理报错信息

  上面的例子中,在异常出现时,捕获后做了自定义的处理,没有保留或打印真正的报错信息;

  可以在except模块中,捕获并抛出真正的错误信息;

# 有两种处理方式
# 一种是不知道会出现什么错误,用Exception做通用的异常捕获

# 以1不能除0为例, 正常情况下,程序执行异常,会直接报错
1 / 0
'''
Traceback (most recent call last):
  File "D:\python_exercise\try_except.py", line 5, in <module>
    1 / 0
ZeroDivisionError: division by zero
'''
# 此时,想拿到Error信息,捕获异常书写方法如下
def test():
    try:
        1 / 0
    except Exception as e:  # as e 给异常信息起个别名e(e可以随意起名,一般大家都习惯写e)
        print(e)

test()
'''
division by zero
'''

# 另一种是提前知道可能出现的异常类型,可直接按已知异常类型捕获
# 例如例子中已知1/0时的ZeroDivisionError
def test2():
    try:
        1 / 0
    except ZeroDivisionError as e:
        print(e)

test2()
'''
division by zero
'''

"""
通用捕获方法,程序执行时需要去异常类型库中找一下报错类型,再去抛出;可能在性能上比指定异常类型差一些,但也可忽略不计;
通用捕获方法,所有异常情况某一种出现都会被抛出,但指定错误类型的方法,当出现其它错误类型时,则不会被抛出,程序依旧报错;
所以两种方式可以按需使用。
"""
# 指定错误类型时,若出现其它错误,程序仍会报错
def test3():
    try:
        3/4
        test_str = 3
        test_str.upper()
    except ZeroDivisionError as e:
        print(e)

test3()
# 此时程序仍会报错
'''
Traceback (most recent call last):
  File "D:\python_exercise\try_except.py", line 51, in <module>
    test3()
  File "D:\python_exercise\try_except.py", line 47, in test3
    test_str.upper()
AttributeError: 'int' object has no attribute 'upper'
'''

  上面的例子中,按类型捕获异常时,是可以同时捕获多种类型的

# 多个异常捕获,依然有两种写法,此时代码中出现某一种错误后就不再进行后续捕获了

# 一种是可以添加多个except模块
def test():
    try:
        1/0
        new_str = 2
        new_str.upper()
    except ZeroDivisionError as e:
        print(e)
    except AttributeError as e:
        print(e)
    print('end')

test()
'''
division by zero
end
'''

# 另一种是写在except元组中
def test2():
    try:
        1/0
        new_str = 2
        new_str.upper()
    except (AttributeError, ZeroDivisionError) as e:
        print(e)
        print(type(e))  # 此时要注意下e不是字符串,是错误类型对应的类
        print(dir(e))   # 打印e的所有可用方法
        print(str(e))   # 有其它需求,可以转化成字符串
    print('end')

test2()
'''
division by zero
<class 'ZeroDivisionError'>
['__cause__', '__class__', '__context__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__suppress_context__', '__traceback__', 'args', 'with_traceback']
division by zero
end
'''

  

4.了解常用的异常类型

  Exception  通用异常类型(基类,是所有异常类型的父类)

  ZeroDivisonError  不能整除0

  AttributeError  对象没有这个属性(或方法)

  IOError  输入输出操作失败 (用于文件读写)

  IndexError  没有当前的索引 (列表、元组中使用)

  KeyError  没有这个键值(key)字典中使用

  NameError 没有这个变量 (未初始化对象)

  SyntaxError  python语法错误

  SystemError  解释器的系统错误 (少见)

  ValueError  传入的参数错误  (函数传参出错)

  TypeError  函数传参类型错误

def test(a):
    print(a)

test()  # 需要一个必传参数(位置参数),但这里是按默认参数有值传递的,会报错
'''
Traceback (most recent call last):
  File "D:\python_exercise\try_except.py", line 57, in <module>
    test()
TypeError: test() missing 1 required positional argument: 'a'
'''
try:
    test()
except TypeError as e:
    print(e)
'''
test() missing 1 required positional argument: 'a'
'''

 

5.finally的功能和用法

  finally是try...except后的额外操作,无论是否发生异常,都会执行finally代码块;

def upper(str_data):
    try:
        new_str = str_data.upper()
        print('try模块执行')
        return new_str
    except AttributeError as e:
        print(e)
    finally:
        print('finally模块执行')
        return 'finally'

# 调用无异常时
re = upper('test')
print(re)
'''
try模块执行
finally模块执行
finally
'''

# 可以看到无异常抛出时,执行try模块后,会继续执行finally模块
# 且当try中有return返回时,也会再执行finally模块,且当finally中也有return时、最终return结果被finally的覆盖


# 调用出现异常时
re2 = upper(3)
print(re2)
'''
'int' object has no attribute 'upper'
finally模块执行
finally
'''

# 可以看到遇到异常后,直接执行了expect模块
# 执行except模块后,依然执行finally模块
# 有时也会只有try...finally一起使用
# 此时出现异常后,不会被捕获,正常报错,但仍会执行finally模块代码
def test():
    try:
        1/0
    finally:
        print('finally执行')

test()
'''
Traceback (most recent call last):
  File "D:\python_exercise\try_except.py", line 119, in <module>
    test()
  File "D:\python_exercise\try_except.py", line 115, in test
    1/0
ZeroDivisionError: division by zero
finally执行
'''

# 此时如果在finally中做return操作
def test2():
    try:
        print('try1')
        1/0
        print('try2')
    finally:
        print('finally执行')
        return 'finally re'

re = test2()
print(re)
'''
try1
finally执行
finally re
'''

# 可以看到遇到异常后未抛出程序异常
# 直接正常执行了finally模块code

  

6.自定义异常与抛出异常

  之前我们看到的Exception, NameError, KeyError等错误类型,都是python中自带的抛出异常类型;

  在平常业务开发中,我们也可以主动定义抛出一些异常,更好的服务于业务;

'''
使用自定义抛出异常函数 --raise
将信息以报错的形式抛出
'''

def test(number):
    if number == 50:
        raise ValueError('数字不能是50')  # raise后的exception类型可以自选
    return number

re = test(100)
print(re)  # 100

re2 = test(50)
print(re2)
'''
Traceback (most recent call last):
  File "D:\python_exercise\try_except.py", line 165, in <module>
    re2 = test(50)
  File "D:\python_exercise\try_except.py", line 159, in test
    raise ValueError('数字不能是50')  # raise后的exception类型可以自选
ValueError: 数字不能是50
'''

# 自定义的错误类型,也是可以通过try...except捕获到的
try:
    test(50)
except Exception as e:
    print(e)
'''
数字不能是50
'''
'''
上述例子中valueError正常是表示参数传递参数错误的错误类型,
和编写的函数中数字值错误并不是很贴切,此时可以使用通用的exception来抛出异常
'''
def test(number):
    if number == 100:
        raise Exception('数值错误,请检查')
    return number

re = test(100)
print(re)
'''
Traceback (most recent call last):
  File "D:\python_exercise\try_except.py", line 194, in <module>
    re = test(100)
  File "D:\python_exercise\try_except.py", line 191, in test
    raise Exception('数值错误,请检查')
Exception: 数值错误,请检查
'''

'''
此时还可以自己编写一个异常类型类,更贴切的描述异常
'''
# 需继承Exception基类
class NumberLimitError(Exception):
    def __init__(self, message):
        self.message = message


def test2(number):
    if number == 100:
        raise NumberLimitError('数值错误,请检查')
    return number
test2(100)
'''
Traceback (most recent call last):
  File "D:\python_exercise\try_except.py", line 219, in <module>
    test2(100)
  File "D:\python_exercise\try_except.py", line 216, in test2
    raise NumberLimitError('数值错误,请检查')
__main__.NumberLimitError: 数值错误,请检查
'''
try:
    test2(100)
except NumberLimitError as e:
    print(e)
'''
数值错误,请检查
'''

# 顺便提下try...except...else
# 无异常出现时,走else逻辑 
try:
    test2(50)
except NumberLimitError as e:
    print(e)
else:
    print('无异常发生')
finally:
    print('finally code')
'''
无异常发生
finally code
'''

 

7.断言

  断言是对一个表达式进行判断,在表达式是false时触发异常;

  断言关键字assert;assert expresion, message ; (expression是要判断的表达式,结果是bool类型;message是遇到错误要抛出的异常信息)

  断言与raise功能类似,相当于对raise的简化写法(使用raise时,会先书写if语句进行判断、再看是否raise抛出异常,assert一行代码就可以搞定这些功能)

assert 1 == 1  # 条件语句为True,正常执行
assert 1 > 2   # 条件语句为False, 会触发报错
"""
Traceback (most recent call last):
  File "D:\python_exercise\try_except.py", line 252, in <module>
    assert 1 > 2
AssertionError
"""
# 此时未指定报错信息,只抛出AssertionError异常,未打印信息


import sys
print(sys.platform)  # win32
assert ('win32' not in sys.platform), '当前PC型号判断有误'
"""
Traceback (most recent call last):
  File "D:\python_exercise\try_except.py", line 262, in <module>
    assert ('win32' not in sys.platform), '当前PC型号判断有误'
AssertionError: 当前PC型号判断有误
"""

    

8.代码bug调试

  bug是程序中的错误,没有提前进行异常捕获,以至于程序报错,导致程序崩溃;

  平常开发中代码量较大时,可能不好定位异常的位置,比较耗时,有两种方式可以帮助我们调试程序找到错误;

  一种是可以借助print打印信息,辅助定位;

a = 1
print('执行到这里1')
b = 2
print('执行到这里2')
c = 3
print('执行到这里3')
print(a, b, c, d)

'''
执行到这里1
执行到这里2
执行到这里3
Traceback (most recent call last):
  File "D:\python_exercise\try_except.py", line 276, in <module>
    print(a, b, c, d)
NameError: name 'd' is not defined. Did you mean: 'id'?
'''
# 可以看到'执行到这里3'已成功打印,说明错误出现在'执行到这里3'下一行 
# (目前代码量较少,程序已直接打印出了出错的位置,代码调用层级较多时,调试效果会更大些)

  另一种是可以借助pycharm的debug功能,利用断点调试程序;

  仍然使用相同的代码,在猜测引起报错位置、想要暂停的地方开头点击一下,形成断点;

  

  点击pycharm右上角的debug按钮,开始执行debug模式;

  

  开始debug执行,可以看到每一步已经自动帮我们标注了变量值变化信息(这里的a: 1), 窗口下方会出现debug操作窗;

  

  发现目前没出现错误,想继续执行可以点击底部弹窗的执行按钮,会执行后续所有的代码(如果后续仍有断点,则执行到下一个断点)

  

  可以看到报错位置已经帮我们标注出来了,代码调用层级较多时,可以帮助我们分段调试代码,比较方便;

  

 

总结

  

 
反对 0举报 0 评论 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

  • SICP:复数的直角和极坐标的表示(Python实现)
    SICP:复数的直角和极坐标的表示(Python实现)
    数据抽象屏障是控制复杂性的强有力工具,然而这种类型的数据抽象还不够强大有力。从一个另一个角度看,对于一个数据对象可能存在多种有用的表示方式,且我们希望所设计的系统能够处理多种表示形式。比如,复数就可以表示为两种几乎等价的形式:直角坐标形式(
    03-16
  • 详解Python手写数字识别模型的构建与使用
    详解Python手写数字识别模型的构建与使用
    目录一:手写数字模型构建与保存1 加载数据集2 特征数据 标签数据3 训练集 测试集4 数据流图 输入层5 隐藏层6 损失函数7 梯度下降算法8 输出损失值 9 模型 保存与使用10 完整源码分享二:手写数字模型使用与测试一:手写数字模型构建与保存1 加载数据集# 1加
  • Python asyncore socket客户端实现方法详解
    Python asyncore socket客户端实现方法详解
    目录介绍1.定义类并且继承 asyncore.dispatcher2.实现类中的回调代码调用父类方法创建socket对象连接服务器3.创建对象并且执行asyncore.loop进入运行循环服务端示例代码运行结果注意介绍asyncore库是python的一个标准库,提供了以异步的方式写入套接字服务的
  • Python+Sklearn实现异常检测
    目录离群检测 与 新奇检测Sklearn 中支持的方法孤立森林 IsolationForestLocal Outlier FactorOneClassSVMElliptic Envelope离群检测 与 新奇检测很多应用场景都需要能够确定样本是否属于与现有的分布,或者应该被视为不同的分布。离群检测(Outlier detectio
  • Python基础教程之while循环用法讲解 Python中的while循环
    Python基础教程之while循环用法讲解 Python中的
    目录1.while 循环2.无限循环3、while 循环使用 else 语句4、简单语句组附小练习:总结1.while 循环Python 中 while 语句的一般形式:while 判断条件(condition):    执行语句(statements)……执行流程图如下:同样需要注意冒号和缩进。另外,在 Python 中
  • Python异常与错误处理详细讲解 python的异常
    基础知识优先使用异常捕获LBYL(look before you leap): 在执行一个可能出错的操作时,先做一些关键的条件判断,仅当满足条件时才进行操作。EAFP(eaiser to ask for forgiveness than permission): 不做事前检查,直接执行操作。后者更优: 代码简洁,效率更高
  • Python Flask利用SocketIO库实现图表的绘制
    Python Flask利用SocketIO库实现图表的绘制
    目录实现简单的数据通信使用SocketIO库绘制主机动态图形Flask 默认提供了针对WebSocket的支持插件from flask_socketio import SocketIO 直接通过pip命令安装即可导入使用,前端也需要引入socketIO库文件,其网站首页是:socket.io/实现简单的数据通信新建inde
  • Python matplotlib之折线图的各种样式与画法总结
    Python matplotlib之折线图的各种样式与画法总
    目录1. 折线形状2. 数据点形状3. 折线颜色4. 添加网格总结上述图的完整代码如下:from numpy import *import numpy as npimport pandas as pdimport matplotlib.pyplot as pltimport pylab as plfrom mpl_toolkits.axes_grid1.inset_locator import inset_axe
  • Python多线程与同步机制浅析
    目录线程实现Thread类函数方式继承方式同步机制同步锁Lock条件变量Condition信号量Semaphore事件Event屏障BarrierGIL全局解释器锁线程实现Python中线程有两种方式:函数或者用类来包装线程对象。threading模块中包含了丰富的多线程支持功能:threading.curren
  • 手把手教你用python绘制热度图(heatmap) python热图怎么画
    手把手教你用python绘制热度图(heatmap) python
    目录1、简单的代码2、添加X轴和Y轴标签和标题:3、对右侧的色条(colorbar)进行调整:4、修改色条的刻度值和标签的字体大小、颜色:5、对热度图显示数值和添加网格线:6、 定义热度图的配色板总结1、简单的代码from matplotlib import pyplot as pltimport sea
点击排行