python异常处理

异常处理

异常就是错误发生的信号,一旦程序出错,并且程序没有处理这个错误,那么就会抛出异常,并且运行的程序随之终止

异常分为两种:语法异常和逻辑异常

语法错误(这种错误,根本过不了python解释器的语法检测,必须在程序执行前就改正过来)

举例说明一下

# 语法异常1
if

# 语法异常2
def test:
    pass

逻辑错误,指的是程序在运行的过程中会发生的错误,这个是无法估算出什么时候发生错误的让我们来举例看一下常见的逻辑错误类型

# 逻辑异常1
int(aaa)  # ----->ValueError

# 逻辑异常2
name  # ---->NameError

# 逻辑异常3
l = [1,2,3]
l[1000]  # ---->IndexError

# 逻辑异常4
d = {}
d['name']  # ---->KeyError

# 逻辑异常5
class Foo:
    pass
Foo.name  # ---->AttributeError

# 逻辑异常6
1/0  # ----> ZeroDivisionError

# 逻辑异常7
for i in 3:
    pass  # ----> TypeError

让我们来看下异常的追踪信息:

Traceback (most recent call last):
  File "D:/py_study/day19-封装和可扩展性/test.py", line 7, in <module>
    int('aaa')
ValueError: invalid literal for int() with base 10: 'aaa'
其中:
	Traceback 代表异常的追踪信息
    ValueError 代表异常的类型
    invalid literal for int() with base 10: 'aaa' 代表 异常的值

关于两种异常的强调

强调一:错误发生的条件如果是可预知的,此时应该用if判断去预防异常

让我们来看一下是如何预防的

AGE = 10
age = input('>>>').strip()

age = int(age)
if age > AGE:
    print('太大了')
    
>>>11
太大了

在这段代码中,我们的age是input用户自己输入的,但是用户会不会输入字符串类型呢?如果用户输入的不是数字,那么程序就会立马报错:
>>>da
Traceback (most recent call last):
  File "D:/py_study/day19-封装和可扩展性/test.py", line 10, in <module>
    age = int(age)
ValueError: invalid literal for int() with base 10: 'da'

那么我们说了,如果错误发生的条件是可以预知的,就应该用if判断去预防
AGE = 10
age = input('>>>').strip()

if age.isdigit():
    age = int(age)
    if age > AGE:
        print('太大了')
在这段程序中,我们做了if去预防异常,如果用户输入的不是数字,那么我们就不做任何操作,程序运行如下
>>>dakodak

强调二:错误发生的条件如果是不可预知的,此时应该用异常处理机制 try...except....

首先在a.txt下定义这些内容
11111111111111111
22222222222222222
33333333333333333

f = open('a.txt','r',encoding='utf-8')
# next(f)  # 相当于f.readline()
try:
    print(next(f),end='')  # 我们并不知道文件有多少行内容
    print(next(f),end='')
    print(next(f),end='')
    print(next(f),end='')
    print(next(f),end='')
    f.close()
except StopIteration:
    print('出错了')

# 运行结果为
11111111111111111
22222222222222222
33333333333333333出错了

在这里需要注意的是,如果我们捕捉的类型和被检测的代码不相符的话,异常还是会抛出的
f = open('a.txt','r',encoding='utf-8')
# next(f)  # 相当于f.readline()
try:
    print(next(f),end='')
    print(next(f),end='')
    print(next(f),end='')
    print(next(f),end='')
    print(next(f),end='')
    f.close() 
except TypeError:  # 捕捉的类型变成了TypeError
    print('出错了')

# 运行结果为
11111111111111111
Traceback (most recent call last):
22222222222222222
33333333333333333  File "D:/py_study/day19-封装和可扩展性/test.py", line 13, in <module>
    print(next(f),end='')
StopIteration  # 还是会抛出异常的

异常的种类

在python中不同的异常可以用不同的类型(Python中统一了类与类型,类型就是类)去标识,一个异常标识一个错误

常见异常

AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
IOError 输入/输出异常;基本上是无法打开文件
ImportError 无法引入模块或包;基本上是路径问题或名称错误
IndentationError 语法错误(的子类) ;代码没有正确对齐
IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
KeyError 试图访问字典里不存在的键
KeyboardInterrupt Ctrl+C被按下
NameError 使用一个还未被赋予对象的变量
SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
TypeError 传入对象类型与要求的不符合
UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,
导致你以为正在访问它
ValueError 传入一个调用者不期望的值,即使值的类型是正确的

更多异常

ArithmeticError
AssertionError
AttributeError
BaseException
BufferError
BytesWarning
DeprecationWarning
EnvironmentError
EOFError
Exception
FloatingPointError
FutureWarning
GeneratorExit
ImportError
ImportWarning
IndentationError
IndexError
IOError
KeyboardInterrupt
KeyError
LookupError
MemoryError
NameError
NotImplementedError
OSError
OverflowError
PendingDeprecationWarning
ReferenceError
RuntimeError
RuntimeWarning
StandardError
StopIteration
SyntaxError
SyntaxWarning
SystemError
SystemExit
TabError
TypeError
UnboundLocalError
UnicodeDecodeError
UnicodeEncodeError
UnicodeError
UnicodeTranslateError
UnicodeWarning
UserWarning
ValueError
Warning
ZeroDivisionError

try...except的详细用法

1.异常类只能用来处理指定的异常情况,如果非指定异常则无法处理

s1 = 'hello'
try:
    int(s1)
except IndexError as e:   # 此时捕捉的异常类型和我们指定的异常是不一样的,所以程序还会抛出异常
    print(e)

2.多分支

s1 = 'hello'
try:
    int(s1)
except IndexError as e:
    print(e)
except KeyError as e:
    print(e)
except ValueError as e:
    print(e)
    
这就属于多分支,当不确定异常的类型时,就可以使用这个

3.万能异常

s1 = 'hello'
try:
    int(s1)
except Exception as e:  # Exception就输入万能异常,什么异常类型都能捕捉到
    print(e)

4.异常的其他机构

# else指的是在try代码块没有异常则执行else里的语句,
s1 = 'hello'
try:
    print(s1)
except Exception as e:
    print(e)
else:
    print('这段程序没有发生异常')
    
# 运行结果为
hello
这段程序没有发生异常

# finally代表无论是否出现异常,都会执行该模块,通常是进行清理工作
s1 = 'hello'
try:
    int(s1)
except Exception as e:
    print(e)
else:
    print('这段程序没有发生异常')
finally:
    print('无论是否出现异常,都会执行该模块,通常是进行清理工作')
    
为什么说是进行清理工作呢?我们看下下面的代码就知道了,在这段代码中,文件正常打开,但是由于没有及时关闭,所以会占用内存,而finally的工作就是清理内存,让内存及时的回收
try:
    f = open('a.txt','r',encoding='utf-8')
    print(next(f))
    print(next(f))
    print(next(f))
    print(next(f))
    print(next(f))
    print(next(f))
finally:
    f.close()

**5.主动触发异常 raise 异常类型(值) **

try:
    raise TypeError('类型错误')
except Exception as e:
    print(e)
    
# 运行结果为
类型错误

我们现在可以在初始化对象的同时去进行判断,如果不符合我们的条件,则主动抛出异常
class People:
    def __init__(self,name,age):  # python的数据类型时没有类型的强制限制
        if not isinstance(name,str):
            raise TypeError('名字必须传入str类型')
        if not isinstance(age,int):
            raise TypeError('年龄必须传入int类型')
        self.name = name
        self.age = age
p = People(333,18)

6.自定义异常类型,类型就是类

class MyException(BaseException):
    def __init__(self,msg):
        super(MyException, self).__init__()
        self.msg = msg

raise MyException('我自己的异常类型')

# 运行结果
Traceback (most recent call last):
  File "D:/py_study/day19-封装和可扩展性/test.py", line 12, in <module>
    raise MyException('我自己的异常类型')
__main__.MyException  # 但是没有异常的值,raise除了把异常的追踪信息和异常信息打出来后,还会打印这个对象的操作

class MyException(BaseException):
    def __init__(self,msg):
        super(MyException, self).__init__()
        self.msg = msg
    def __str__(self):
        return '<%s>'%self.msg
raise MyException('我自己的异常类型')

# 此时的运行结果是
Traceback (most recent call last):
  File "D:/py_study/day19-封装和可扩展性/test.py", line 13, in <module>
    raise MyException('我自己的异常类型')
__main__.MyException: <我自己的异常类型>

7.总结try...except

1.把错误处理和真正的工作分开来,就是不要在程序的开头写上try,在结尾写except,这样是一点用都没有的
2.代码更易组织,更清晰,复杂的工作任务更容易实现
3.更安全了,不会因为一些小的疏忽而使程序意外崩溃了
原文地址:https://www.cnblogs.com/xiaoyafei/p/9113100.html