Python基础教程(第三版)读书笔记(8)

异常

异常就是不正常的情况。Python提供了强大的异常处理机制。python使用异常对象来表示异常状态,并在遇到错误时引发异常。

>>> 1/0
Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    1/0
ZeroDivisionError: division by zero

上面是一个分子为零的异常。异常未被捕获时,程序将终止并返回一条错误信息(Traceback)。

自主引发异常——raise语句

出现异常时,将自动引发异常。也可以使用raise语句自主引发异常。看下面的例子。

>>> raise Exception
Traceback (most recent call last):
  File "<pyshell#5>", line 1, in <module>
    raise Exception
Exception

上面是释放一个内置异常类Exception,也可以在异常里添加错误信息。

>>> raise Exception('Test example')
Traceback (most recent call last):
  File "<pyshell#8>", line 1, in <module>
    raise Exception('Test example')
Exception: Test example

一些内置的异常类

类名 描述
Exception 几乎所有的异常类都是从它派生而来的
AttributeError 引用属性或给它赋值失败时引发
OSError 操作系统不能执行指定的任务(如打开文件)时引发,有多个子类
IndexError 使用序列中不存在的索引时引发,为LookupError的子类
KeyError 使用映射中不存在的键时引发,为LookupError的子类
NameEroor 找不到名称(变量)时引发
SyntaxError 代码不正确时引发
TypeError 将内置操作或函数用于类型不正确的对象时引发
ValueError 将内置操作或函数用于这样的对象时引发:其类型正确但包含的值不合适
ZeroDivisionError 在除法或者求模运算的第二个参数为零时引发

自定义创建异常类

除了释放内置的异常类,也可以自定义创建异常类。创建异常类很简单,和创建其他类一样。但是需要直接或者间接的继承Exception(这意味着从任何内置异常类派生都可以。)

>>> class Firstexception(Exception):
	pass

>>> raise Firstexception
Traceback (most recent call last):
  File "<pyshell#14>", line 1, in <module>
    raise Firstexception
Firstexception

捕获异常 try/excepy语句

接下来是最有趣的地方了,捕获异常。如果你觉得某段代码可能会引发异常,可以使用try / except语句捕获异常。

>>> try:
	x = int(input('data1: '))
	y = int(input('data2: '))
	print(x / y)
except ZeroDivisionError:
	print("The second number can't be zero!")


data1: 2
data2: 0
The second number can't be zero!

捕获异常后,可以在except语句块中进行相应的处理措施。如果想要重新引发异常(异常继续向上传播),可调用raise语句且不提供任何参数。看下面这个例子,类MuffledCalculator中的属性muffled如果为TRUE时,异常会被处理。当muffled为false时,异常会被再次引发。

>>> class MuffledCalculator:
	muffled = False
	def clac(self, expr):
		try:
			return eval(expr)
		except ZeroDivisionError:
			if self.muffled:
				print('Division by zero is illeagl')
			else:
				raise

			
>>> calculator = MuffledCalculator()
>>> calculator.clac('10 / 2')
5.0
>>> calculator.clac('10 / 0')
Traceback (most recent call last):
  File "<pyshell#14>", line 1, in <module>
    calculator.clac('10 / 0')
  File "<pyshell#11>", line 5, in clac
    return eval(expr)
  File "<string>", line 1, in <module>
ZeroDivisionError: division by zero
>>> calculator.muffled = True
>>> calculator.clac('1 / 0')
Division by zero is illeagl

如果无法处理异常,except语句中使用raise是一个很好的选择。另外,如果想要引发其他异常,那么导致进入except语句的异常将被作为异常上下文存储起来。

>>> try:
	a = 1/0
except ZeroDivisionError:
	raise ValueError

Traceback (most recent call last):
  File "<pyshell#37>", line 2, in <module>
    a = 1/0
ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<pyshell#37>", line 4, in <module>
    raise ValueError
ValueError

也可使用raise…from…自己提供上下文。raise…from…None表示禁用上下文。

>>> try:
	a = 1/0
except ZeroDivisionError:
	raise ValueError from Exception

Exception

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<pyshell#47>", line 4, in <module>
    raise ValueError from Exception
ValueError
>>> try:
	a = 1/0
except ZeroDivisionError:
	raise ValueError from None

Traceback (most recent call last):
  File "<pyshell#49>", line 4, in <module>
    raise ValueError from None
ValueError

如果想要处理多个异常。如果多个异常想要分开处理,可以使用多个except语句。

>>> try:
	x = int(input('data1: '))
	y = int(input('data2: '))
	print(x / y)
except ZeroDivisionError:
	print("The second number can't be zero")
except TypeError:
	print("That wasn't a number, was it?")

	
data1: 1
data2: 0
The second number can't be zero

多个异常处理方法一样时,可在一个元组里指定这些异常。

>>> try:
	x = int(input('data1: '))
	y = int(input('data2: '))
	print(x / y)
except (ZeroDivisionError, TypeError, NameError):
	print('Your numbers were bogus...')

	
data1: 1
data2: 0
Your numbers were bogus...

else 子句

异常与句块可以加上else语句。会在没有异常时执行。

>>> while True:
	try:
		x = int(input('data1:'))
		y = int(input('data2:'))
		value = x/y
		print('x/y is', value)
	except:
		print('Invalid input. Please try again.')
	else:
		break

	
data1:1
data2:0
Invalid input. Please try again.
data1:jk
Invalid input. Please try again.
data1:j
Invalid input. Please try again.
data1:jkj
Invalid input. Please try again.
data1:2
data2:jkj
Invalid input. Please try again.
data1:1
data2:2
x/y is 0.5

finally字句

最后介绍一下finally子句。可用于在发生异常时执行清理工作。不管try子句中是否发生异常都会执行finally子句。

>>> try:
	1/0
except NameError:
	print('Unknown variable')
else:
	print('That went well!')
finally:
	print('Cleaning up.')

	
Cleaning up.
Traceback (most recent call last):
  File "<pyshell#88>", line 2, in <module>
    1/0
ZeroDivisionError: division by zero

警告

再说一下警告(处理不那么严重的情况)把,警告可使用warning模块中的函数warn。

>>> from warnings import warn
>>> warn('hhhh')

Warning (from warnings module):
  File "__main__", line 1
UserWarning: hhhh

小结

  • 异常对象: 异常情况(如发生错误)是用异常对象表示的。对于异常情况,有多种处理方式;如果忽略,将导致程序终止。
  • 引发异常: 可使用raise语句来引发异常。它将一个异常类或异常实例作为参数,但你可以提供两个参数(异常和错误消息)。如果在except子句中调用raise时没有提供参数,它将重新引发该子句捕获的异常。
  • 捕获异常: 要捕获异常,可在try语句中使用except子句。在except子句中,如果没有指定异常类,将捕获所有的异常。你可以指定多个异常类,方法是将它们放在元组中。如果想except提供两个参数,第二个参数将关联到异常对象。在同一条try/except语句中,可包含多个except子句,以便对不同的异常采取不同的措施。
  • 警告: 警告类似于异常,但(通常)只打印一条错误信息。你可以指定警告类别,它们是warning的子类。

本章学习的函数:

函数 描述
warnings.filterwarnings(action, category=Warning, …) 用于过滤警告
warnings.warn(message, category=None) 用于发出警告
发布了14 篇原创文章 · 获赞 8 · 访问量 224

猜你喜欢

转载自blog.csdn.net/weixin_43582715/article/details/104028372