Python之异常处理

异常处理

异常和错误

错误

1/0
name
2+'3'
[][3]
{}['k']
都是错误

1.语法错误

当出现语法错误时,程序则无法通过程序解释器,会直接报错,必须在程序执行前进行解决。

#错误1

if a

#错误2

print (123
注意在Python2中,print可以不加括号即print 123是正确的

#错误3

def  func:
       pass
View Code

2.逻辑错误

#数字无法和字符串直接相加

des=4+'str'
def=1/0

何为异常?

异常就是程序运行时发生错误的信号,在python中,错误触发的异常如下:

Python中的异常种类

在python中不同的异常可以用不同的类型(python中统一了类与类型,类型即类)去标识,不同的类对象标识不同的异常,一个异常标识一种错误。

l=['on','aa']
l[3]
索引错误:IndexError
dic={'name':'eric'}
dic['age']
键错误:KeyError
s='hello'#无法转成数字类型
int(s)

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

异常处理

1.异常:当程序发生异常 之后,异常之后的程序将不再执行。

2.异常处理:python解释器检测到错误,触发异常(也允许程序员自己触发异常),程序员编写特定的代码,专门用来捕捉这个异常(这段代码与程序逻辑无关,与异常处理有关)

如果捕捉成功则进入另外一个处理分支,执行你为其定制的逻辑,使程序不会崩溃,这就是异常处理。

3.为什么要进行异常处理?

  python解析器去执行程序,检测到了一个错误时,触发异常,异常触发后且没被处理的情况下,程序就在当前异常处终止,后面的代码不会运行。为了增强你程序的健壮性与容错性,必须提供一种异常处理机制来进行约束。这样就可以在一些不重要的错误出现时通过异常处理机制就可以将其处理,而不会使其成为程序运行的障碍。

4.如何进行异常处理?

 首先须知,异常是由程序的错误引起的,语法上的错误跟异常处理无关,必须在程序运行前就修正。

(一) 使用if判断式

num1=input('>>: ') #输入一个字符串试试
int(num1)
正常代码
num1=input('>>: ')  #输入一个字符串试试
if num1.isdigit():  #判断输入的字符串是否为数字
    int(num1)       #我们的正统程序放到了这里,其余的都属于异常处理范畴
elif num1.isspace():#判断是否为空格
    print('输入的是空格,就执行我这里的逻辑')
elif len(num1) == 0:#输入的长度是否为空,既没有输入
    print('输入的是空,就执行我这里的逻辑')
else:               #其他情况
    print('其他情情况,执行我这里的逻辑')

#问题一:使用if的方式我们只为第一段代码加上了异常处理,但这些if,跟你的代码逻辑并无关系,这样你的代码会因为可读性差而不容易被看懂
#问题二:这只是我们代码中的一个小逻辑,如果类似的逻辑多,那么每一次都需要判断这些内容,就会导致我们的代码特别冗长。
#问题三:这只是在我们已知可能出现的错误下,给出的容错判断,还有可能出现许多未知的错误,如果我们针对每一种错误都要给出一种合理的处理机制,我们的代码量将可能成倍的增加。
利用if判断进行异常处理

总结:
1.只能针对某一种或某一类,出现别的错误的需要添加if判断。
2.频繁地出现错误检测代码,使程序可读性更差。
3.由于会出现以上两个问题,所以在慎用。

(二) python为每一种异常定制了一个类型,然后提供了一种特定的语法结构用来进行异常处理

基本语法:

try:
     被检测的代码块
except 异常类型:
     try中一旦检测到异常,就执行这个位置的逻辑
语法代码
f = open('a.txt')
g = (line.strip() for line in f)#生成器
for line in g:#调用一次g执行一次生成器中的代码
    print(line)
else:
    f.close()
文件读取实例
try:
    f = open('a.txt')
    g = (line.strip() for line in f)
    print(next(g))#next执行一次调用一次生成器,直至生成器中的内容取完,如果再进行取值,则会出错,错误为StopIteration
    print(next(g))
    print(next(g))
    print(next(g))
    print(next(g))
except StopIteration:#通过执行判断当出现这个错误时,说明值已取完,就可以关闭文件了。
    f.close()
加入try……except判断

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

# 未捕获到异常,程序直接报错
 s1 = 'hello'
try:
    int(s1)
except IndexError as e:
    print e
由于在程序中执的整个过程中,没有出现相关要捕获的错误类别,所以还是会报错。
指定某种异常

2.2 多分支

s1 = 'hello'
try:
    int(s1)
except IndexError as e:
    print(e)
except KeyError as e:
    print(e)
except ValueError as e:
    print(e)

虽然通过多分支使代码的容错性加强,但是这种特有错误的判断使得当没有出现相关的检测错误代码时,还是会报错。
多分支

2.3 万能异常 在python的异常中,有一个万能异常:Exception,他可以捕获任意异常,即:

s1 = 'hello'
try:
    int(s1)
except Exception as e:
    print(e)
#此种情况下,只要出错,都会进入except中执行其中的代码。
View Code

你可能会说既然有万能异常,那么我直接用上面的这种形式就好了,其他异常可以忽略.你说的没错,但是应该分两种情况去看:
1) 如果你想要的效果是,无论出现什么异常,我们统一丢弃,或者使用同一段代码逻辑去处理他们,那么骚年,大胆的去做吧,只有一个Exception就足够了。

s1 = 'hello'
try:
    int(s1)
except Exception,e:
    '丢弃或者执行其他逻辑'
    print(e)

#如果你统一用Exception,没错,是可以捕捉所有异常,但意味着你在处理所有异常时都使用同一个逻辑去处理(这里说的逻辑即当前expect下面跟的代码块)
View Code

2)如果你想要的效果是,对于不同的异常我们需要定制不同的处理逻辑,那就需要用到多分支了。

s1 = 'hello'
try:
    int(s1)
except IndexError as e:
    print(e)
except KeyError as e:
    print(e)
except ValueError as e:
    print(e)
多分支
s1 = 'hello'
try:
    int(s1)
except IndexError as e:
    print(e)
except KeyError as e:
    print(e)
except ValueError as e:
    print(e)
except Exception as e:
    print(e)
多分支+Exception

2.4 异常的其他机构

s1 = 'hello'
try:
    int(s1)
except IndexError as e:
    print(e)
except KeyError as e:
    print(e)
except ValueError as e:
    print(e)
#except Exception as e:
#    print(e)
else:
    print('try内代码块没有异常则执行我')
finally:
    print('无论异常与否,都会执行该模块,通常是进行清理工作')
其他异常机构
try:
    print('1111')              以此行为第一行
    1/0              #1处
    print('2222')
    # name       #2处
    # 2+'3'
    # [][3]
    # {}['k']
    ret = int(input('number >>>'))
    print(ret*'*')
except ValueError:
    print('输入的数据类型有误')
except Exception:
    print('你错了,老铁')
else:
    print('没有异常的时候执行else中的代码')
print('===========')

#如果将1出的错误放开,则会只执行第1、2、12、13、16行对应代码
#如果仅仅将2处的错误放开,则程序会多执行一行,即第3行
eg:

2.5 主动触发异常

try:
    raise TypeError('类型错误')
except Exception as e:
    print(e)
主动触发

2.6 自定义异常

class EvaException(BaseException):
    def __init__(self,msg):
        self.msg=msg
    def __str__(self):
        return self.msg

try:
    raise EvaException('类型错误')
except EvaException as e:
    print(e)
自定义

2.7 断言

assert 1 == 1
assert 1 == 2
断言

2.8 try……except的好处

try..except这种异常处理机制就是取代if那种方式,让你的程序在不牺牲可读性的前提下增强健壮性和容错性。
异常处理中为每一个异常定制了异常类型,对于同一种异常,一个except就可以捕捉到,可以同时处理多段代码的异常,减少了代码,增强了可读性

使用try..except的方式
1:把错误处理和真正的工作分开来。
2:代码更易组织,更清晰,复杂的工作任务更容易实现。
3:毫无疑问,更安全了,不至于由于一些小的疏忽而使程序意外崩溃了。

 

 

posted on 2019-11-24 11:27  眨眼星舟_Eric  阅读(119)  评论(0)    收藏  举报

导航