python中的异常处理(小白必看的史上最全异常处理总结!)【下篇】


接上篇文章:
python中的异常处理(小白必看的史上最全异常处理总结!)【上篇】

raise

在这里插入图片描述

当程序出现错误时,系统会自动引发异常。除此之外,python也允许程序自动引发异常,自行引发异常使用raise来完成

引发异常

其实异常是一种主观的说法,对我们来说是一件不好的事,但对另一方面来说可能并不是那么糟糕。就拿实际中的例子来说,近来北京天天下雨,就好比我周六约了朋友去打篮球,结果周六那天突降大雨,篮球我是打不了了,这就打破了我原定的计划,对于我来说这就是一种异常,但是另一方面,转眼干旱地区和农作物现在正需要点雨水的滋润,那对于他们来说这就是正常的。
所以很多时候,系统是否要引发异常,可能需要根据应用的业务需求来定,如程序中的数据、执行与既定的业务需求不符,这就是一种异常。由于与业务需求不符而产生的异常必须由程序员来决定引发,系统是无法引发这种异常的。
如果想要在程序中自行引发异常,就需要用到raise语句了
raise语句有的三种常用的方法:
1、raise:这是单独的一个raise。该语句引发当前上下文中捕获的异常(如在except块中),或者默认引发RuntimeError异常
2、raise 异常类:raise后带一个异常类。该语句引发指定异常类的默认实例
3、raise 异常对象:引发指定的异常对象
这三种最终都要引发一个异常实例(即指定的是异常类,实际上也是引发该类的默认实例),raise语句每次只能引发一个异常实例。
raise的作用:显式的抛出异常。当出现异常时,raise后面的语句就不会执行

def test(count):
    if count == 100:
        raise ValueError("I am error")
    print(count)
test(100)

运行结果:

Traceback (most recent call last):
  File "D:/PycharmProjects/wangyongha/爬虫/pachong.py", line 718, in <module>
    test(100)
  File "D:/PycharmProjects/wangyongha/爬虫/pachong.py", line 715, in printCount
    raise ValueError("I am error")
ValueError: I am error
※如果test()传参不等于100,那么就直接执行print(count)语句

raise后面可以是一个class、也可以是一个对象

def test(count):
    if count == 100:
        raise ValueError("I am error")       #这是实例对象
        #raise ValueError                    #这是class
    print(count)

try:
    test(100)
except ValueError as e:  #e为ValueError对象
    print(e)
或者
# try:
#     test(100)
# except ValueError:
#     print('我捕获到一个valueError错误')

运行结果:

I am error

当python解释器接收到开发者自行引发异常时,同样会终止当前的执行流,跳到异常对应的except块,由except块来处理异常。也就是说不管是系统自动引发的异常还是我们自己手动引发的异常,python解释器对异常的处理其实没有任何差别。

自定义异常类

很多时候,程序可选择引发自定义异常,因为异常的类名通常也包含了该异常的有用信息。所以在引发异常时,应选择合适的异常类,从而可以明确的描述该异常情况。
用户自定义异常类都应该继承Eexception基类或者Exception的子类,在自定义异常类时基本不需要写更多的代码,只需要指定自定义异常类的父类就可以了
例:

class AuctionException(Exception):
	pass 

自定义异常类需要实现__str__方法来定义需要抛出的异常信息
raise语句主动抛出异常。
捕获异常需要通过try…except 语句,其中"except"语句必须有用相同的异常(或者直接抛出Exception)来抛出类对象

#1.用户自定义异常类型
class TooLongExceptin(Exception):

    def __init__(self,Leng):
        self.leng = Leng
    def __str__(self):
        print("姓名长度是"+str(self.leng)+",超过长度了")
#!/usr/bin/python
# -*- coding: UTF-8 -*-
def name_Test():
    try:
        name = input("enter your naem:")
        if len(name)>4:
            raise TooLongExceptin(len(name))
        else :
            print(name)
 
    except TooLongExceptin as e_result:  #e_result是基于TooLongExceptin类创建的实例     print("捕捉到异常了")
        print("打印异常信息:",e_result)
 
#调用函数,执行                                                                    
name_Test()

运行结果:

C:\Users\admin\AppData\Local\Programs\Python\Python39\python.exe C:/Users/admin/Desktop/test.py
enter your naem:223rfsv
Traceback (most recent call last):
  File "C:\Users\admin\Desktop\test.py", line 7, in name_Test
    raise TooLongExceptin(len(name))
NameError: name 'TooLongExceptin' is not defined

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\admin\Desktop\test.py", line 15, in <module>
    name_Test()
  File "C:\Users\admin\Desktop\test.py", line 11, in name_Test
    except TooLongExceptin as e_result:  #e_result是基于TooLongExceptin类创建的实例     print("捕捉到异常了")
NameError: name 'TooLongExceptin' is not defined

Process finished with exit code 1

在这里插入图片描述

except和raise同时使用

在实际应用中对异常可能需要更复杂的处理方式,当一个异常出现时,单靠某个方法无法完全处理该异常,必须由几个方法协作才可以完成处理该异常,也就是说在异常出现的当前方法中,程序只对异常进行部分处理,还有一些处理需要在该方法的调用者中才能完成,所以应该再次引发异常,让该方法的调用者也能捕获到异常。
这个可以通过在except块中结合raise语句来完成
例:

class AuctionException(Exception): pass
class AuctionTest:
	def __init__(self,init_price):
		self.init_price = init_price
	def bid(self,bid_price):
		d = 0.0
		try:
			d = float(bid_price)
		except Exception as e:
			print("转换出异常:",e)
			#再次引发自定义异常
			raise AuctionException("竞拍价必须是数值,不能包含其他字符!")
		if self.init_price > d:
			raise AuctionException("竞拍价比起拍价低,不允许竞拍!")
		init_price = d
def main():
	at = AuctionTest(20.4)
	try:
		at.bid("df")
	except AuctionException as ae:
		#再次捕获到bid()方法中的异常,并对该异常进行处理
		print('main函数捕获的异常:',ae)
main()	

运行结果:

转换出异常: could not convert string to float: 'df'
main函数捕获的异常: 竞拍价必须是数值,不能包含其他字符!

raise不需要参数

在使用raise语句时可以不带参数,此时raise语句处于except块中,它将会自动引发当前上下文激活的异常,否则,通常默认引发RuntimeError异常。

class AuctionException(Exception): pass
class AuctionTest:
	def __init__(self,init_price):
		self.init_price = init_price
	def bid(self,bid_price):
		d = 0.0
		try:
			d = float(bid_price)
		except Exception as e:
			print("转换出异常:",e)
			#再次引发自定义异常
			raise
		if self.init_price > d:
			raise AuctionException("竞拍价比起拍价低,不允许竞拍!")
		init_price = d
def main():
	at = AuctionTest(20.4)
	try:
		at.bid("df")
	except AuctionException as ae:
		#再次捕获到bid()方法中的异常,并对该异常进行处理
		print('main函数捕获的异常:',type(ae))
main()	

运行结果:

ValueError: could not convert string to float: 'df'
转换出异常: could not convert string to float: 'df'

python的异常传播轨迹

异常对象提供了一个with_traceback用于处理异常的传播轨迹
例:

class SelfException(Exception):
	pass
def main():
	firstMethod()
def firstMethod():
	secondMethod()
def secondMethod():
	thirdMethod()
def thirdMethod():
	raise SelfException("自定义异常信息")
main()

运行结果:
在这里插入图片描述
python专门提供了traceback模块来处理异常传播轨迹,导入traceback模块之后,traceback提供了两个常用的方法
1、traceback.print_exc():将异常传播轨迹信息输出到控制台或指定文件中
2、format_exc():将异常传播轨迹信息转换成字符串
例:

#导入traceback模块
import traceback
class SelfException(Exception):
	pass
def main():
	firstMethod()
def firstMethod():
	secondMethod()
def secondMethod():
	thirdMethod()
def thirdMethod():
	raise SelfException("自定义异常信息")
try:
	main()
except:
	#捕获异常,并将异常传播信息输出到控制台
	traceback.print_exc()
	#捕获异常,并将异常传播信息输出到指定文件中
	traceback.print_exc(file=open('log.txt','a'))

运行结果:
在这里插入图片描述
在这里插入图片描述

异常处理规则

异常处理的目的:
1、使程序代码混乱最小化
2、捕获并保留诊断信息
3、通知相关人员
4、采用合适的方法结束异常
异常处理规则:
1.不要过度使用异常
不要把异常和普通错误混淆在一起,不再编写任何错误处理代码,而是以简单地 发异常来代替所有的错误处理。
不要使用异常处理来代替正常的程序流程控制。
2.不要使用庞大的try块
当try块过于庞大时,就难免在 try 块后紧跟大量的 except 块才可以针对不同的异常提供不同的处理逻辑。在同 try 块后紧跟大量 except 块则需要分析他们之间的逻辑关系,反而增加了编程复杂度 。
正确的做法是,把大块的 try 块分割成多个可能出现异常的程序段落,并把它们放在单独的 try块中,从而分别捕获并处理异常。
3.不要忽略捕捉到的异常,可以对异常采取适当措施。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

十七光年

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

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

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

打赏作者

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

抵扣说明:

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

余额充值