异常
例题引导:编写一个计算减法的方法,自己输入两个数,当第一个数小于第二个数时,抛出“被减数不能小于减数”的异常。
解题思路:首先需要一个判断的语句,比较两个数大小,其次需要定义异常,主要掌握try/except语句
参考答案:
def jianfa(a,b):
if a<b:
raise BaseException('被减数不能小于减数')
#return 0
else:
return a-b
try:
a=int(input())
b=int(input())
print(jianfa(a, b))
print("没遇到自己定义的错误") #不打印
except:
print("被减数不能小于减数")
finally:
print("OK")
学习引导:
- 语法错误
- 处理异常
- 异常else
- 异常finally
- 自定义异常
异常
在我们刚接触python的时候,肯定遇到过无数次的报错。
python中有两种错误很容易辨认:语法错误和异常。
语法错误
python的语法错误又称为解析错,多数是语法格式上出现问题。比如:
print('Hello World') #这里的括号为中文格式下的,所以报错
File "<ipython-input-1-f552c294b592>", line 1
print('Hello World')
^
SyntaxError: invalid character in identifier
处理异常
即使python程序的语法是正确的,在运行它时也可能报错。
运行过程中出现的错误称为异常。
大多数的异常不会被程序自动处理,因此产生错误信息(即报错)
异常捕捉可以用try/except语句:
while True:
try:
x=int(input('请输入一个数字:'))
break
except ValueError:
print('您输入的不是数字,请再次尝试输入!')
'''
请输入一个数字:s
您输入的不是数字,请再次尝试输入!
请输入一个数字:3
'''
try 语句按照如下方式工作;
首先,执行 try 子句(在关键字 try 和关键字 except 之间的语句)。
如果没有异常发生,忽略 except 子句,try 子句执行后结束。
如果在执行 try 子句的过程中发生了异常,那么 try 子句余下的部分将被忽略。如果异常的类型和 except 之后的名称相符,那么对应的 except 子句将被执行。
如果一个异常没有与任何的 except 匹配,那么这个异常将会传递给上层的 try 中。
捕获指定异常:
try:
<语句>
except<异常名>:
print('异常说明')
一个例子:
try:
f = open("file-not-exists", "r") #试图打开一个本不存在的文件
except IOError as e: #IOErro:指要打开的文件不存在的错误提示,Try语句的错误与expect匹配,执行print语句。
print("open exception: %s: %s" %(e.errno, e.strerror))
#open exception: 2: No such file or directory
捕获多个异常
捕获多个异常有两种方式,第一种是一个except同时处理多个异常,不区分优先级:
try:
<语句>
except (<异常名1>, <异常名2>, ...):
print('异常说明')
第二种是区分优先级的:
try: <语句>
except <异常名1>:
print('异常说明1')
except <异常名2>:
print('异常说明2')
except <异常名3>:
print('异常说明3')
实例如下:
import sys
try:
f = open('myfile.txt') #打开文件
s = f.readline() #按行读取
i = int(s.strip()) #都成整数类型
except OSError as err:
print("OS error: {0}".format(err)) #文件读取错误优先解决
except ValueError:
print("Could not convert data to an integer.")
except:
print("Unexpected error:", sys.exc_info()[0])
raise
#OS error: [Errno 2] No such file or directory: 'myfile.txt'
该种异常处理语法的规则是:
执行try下的语句,如果引发异常,则执行过程会跳到第一个except语句。
如果第一个except中定义的异常与引发的异常匹配,则执行该except中的语句。
如果引发的异常不匹配第一个except,则会搜索第二个except,允许编写的except数量没有限制。
如果所有的except都不匹配,则异常会传递到下一个调用本代码的最高层try代码中。
异常的else
如果判断完没有某些异常之后还想做其他事,就可以使用下面这样的else语句。
try:
<语句>
except <异常名1>:
print('异常说明1')
except <异常名2>:
print('异常说明2')
else:
<语句> # try语句中没有异常则执行此段代码
异常的finally
try…finally…语句无论是否发生异常都将会执行最后的代码。
try:
<语句>
finally:
<语句>
一个实例如下:
str1 = 'hello world'
try:
int(str1)
except IndexError as e:
print(e)
except KeyError as e:
print(e)
except ValueError as e:
print(e)
else:
print('try内没有异常')
finally:
print('无论异常与否,都会执行我')
#invalid literal for int() with base 10: 'hello world'
#无论异常与否,都会执行我
自定义异常
自定义类继承Exception
你可以通过创建一个新的异常类来拥有自己的异常。异常类继承自 Exception 类,可以直接继承,或者间接继承。
在try语句块中,抛出用户自定义的异常后执行except部分,变量 e 是用于创建MyError类的实例。
实例如下:
class MyError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
try:
raise MyError(2*2)
except MyError as e:
print('My exception occurred, value:', e.value)
#My exception occurred, value: 4
raise MyError('oops!')
MyError Traceback (most recent call last)
<ipython-input-16-3e3ae366964f> in <module>
----> 1 raise MyError('oops!')
MyError: 'oops!'
在上述例子中,类 Exception 默认的 __ init__() 被覆盖。
当创建一个模块有可能抛出多种不同的异常时,一种通常的做法是为这个包建立一个基础异常类,然后基于这个基础类为不同的错误情况创建不同的子类:
class Error(Exception):
"""Base class for exceptions in this module."""
pass
class InputError(Error):
"""Exception raised for errors in the input.
Attributes:
expression -- input expression in which the error occurred
message -- explanation of the error
"""
def __init__(self, expression, message):
self.expression = expression
self.message = message
class TransitionError(Error):
"""Raised when an operation attempts a state transition that's not
allowed.
Attributes:
previous -- state at beginning of transition
next -- attempted new state
message -- explanation of why the specific transition is not allowed
"""
def __init__(self, previous, next, message):
self.previous = previous
self.next = next
self.message = message
大多数的异常的名字都以”Error”结尾,就跟标准的异常命名一样。
raise自定义异常类
raise语法格式如下:
raise [Exception [, args [, traceback]]]
语句中Exception是异常的类型(例如ValueError),参数是一个异常参数值。该参数是可选的,如果不提供,异常的参数是”None”。最后一个参数是跟踪异常对象,也是可选的(在实践中很少使用)。
def not_zero(num):
try:
if num == 0:
raise ValueError('参数错误')
return num
except Exception as e:
print(e)
not_zero(0)
#参数错误
小作业:
- 简述如下各常见异常的含义并举例:SyntaxError、KeyError、IndexError、AttributeError、OSError、TypeError