Python初级009-错误与异常

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python初级009-错误与异常相关的知识,希望对你有一定的参考价值。

错误与异常

目录:

----------什么是错误与异常

1、1、异常类

----------捕捉异常并处理

1try...except的初步使用

2、try...except的捕获异常分析(一)

3、try...except的捕获异常分析(二)

4、try...except的捕获异常分析(三)

5、try...except的捕获异常分析(四)

6、try ... except...else的捕获异常分析(一)

7、try ... finally....的捕获异常分析(一)

8、try ... except....finally....的捕获异常分析(综合应用)

9、With语句的捕获异常分析(综合应用)

----------raiseassert语句

1raise语句

2assert语句

----------标准异常和自定义异常

 

一、什么是错误与异常?

错误:在执行前就出现错误

1、语法错误:代码不符合解释器或者编译器语法

2、逻辑错误:不完整或者不合法输入或者计算出现问题

异常:执行过程中出现问题导致程序无法执行

1、程序遇到逻辑或者算法问题

2、运行过程中计算错误(内存不够或者IO错误)  

错误与异常的区别:

错误:

1、代码运行前的语法或者逻辑错误

2、语法错误在执行前修改,逻辑错误无法修改

异常:代码运行后的

1、异常产生,检查错误且解释器认为是异常,跑出异常

2、异常处理,截获异常,忽略或者终止程序处理异常

 

Python中用异常对象来表示异常情况。通常遇到错误后,就会引发异常,每一个异常都是一些类的实例。这些实例可以被引发,并且可以用很多种方法 进行捕捉,是的程序可以捕捉错误并对其进行处理。

 

1.Python异常类

   Python是面向对象语言,所以程序抛出的异常也是类。常见的Python异常有以下几个,大家只要大致扫一眼,有个映像,等到编程的时候,相信大家肯定会不只一次跟他们照面(除非你不用Python了)。

   Python中的内建异常类

异常

描述

NameError

尝试访问一个没有申明的变量

ZeroDivisionError

除数为0的错误

SyntaxError

语法错误

IndexError

索引超出序列范围

KeyError

请求一个不存在的字典关键字

IOError

输入输出错误(比如你要读的文件不存在)

AttributeError

尝试访问未知的对象属性

ValueError

传给函数的参数类型不正确,比如给int()函数传入字符串形

 

例子:常见的错误---代码运行前

>>> a

Traceback (most recent call last):

  File "<pyshell#4>", line 1, in <module>

    a

NameError: name ‘a‘ is not defined

 

例子:常见的异常---代码运行后

>>> print (1/0)

Traceback (most recent call last):

  File "<pyshell#0>", line 1, in <module>

    print (1/0)

ZeroDivisionError: division by zero

 

>>> while True print("Hello World")

SyntaxError: invalid syntax

 

 

 

二、捕捉异常并处理

===============================================================================

try...except的初步使用

python中的异常使用继承结构创建,可以在异常处理程序中捕获基类异常,也可以捕获各种子类异常,python中使用try...except语句捕获异常,异常子句定义在try子句后面。

try子句中的代码块放置可能出现异常的语句,except子句中的代码块处理异常。

 

语法的整体结构

技术分享 

解释:

1、try是用来捕获try_suite块中的错误,并且将错误交给except处理。

2、try下面的try_suite块指的是需要被处理的逻辑代码,检测是否具有异常。

3、except是用接收try所捕获的异常的,如果处理异常和设置捕获异常一致,使用Exception_block处理异常。(当处理异常和设置捕获异常不一致时,此异常就会被解释器直接处理。)

4、后面的Exception是指内建异常类,称为设置异常,用来与try_suite块所捕获到的异常类相匹配,看看是否相等。

5、.[e] 是指变量,用于保存所出现的错误异常的信息。(如果处理异常和捕获异常不一致时,它就是用来保存解释器直接处理的错误信息。)

6、exception_block指的的用来处理捕获异常的逻辑。

 

例子:

[[email protected] ~]# cat error.py

#!/usr/bin/python

a

print "exec over"

[[email protected] ~]# ./error.py

Traceback (most recent call last):

  File "./error.py", line 2, in <module>

    a

NameError: name ‘a‘ is not defined

解析:

这里的aprint "exec over"是属于同一个程序块,a没有被定义,所以不能输出。

 

 

例子:

[[email protected] ~]# cat error.py

#!/usr/bin/python

try:

a

except NameError,e:

print "catch Error:",e

print "exec over"

[[email protected] ~]# ./error.py

catch Error: name ‘a‘ is not defined

exec over

解析:

try捕获到a没有被定义就使用了,将存在的异常交给except处理,捕获异常与处理异常类型一致,e指的是存放处理信息,捕捉到的异常被处理得到的信息就是“name ‘a‘ is not defined”。print "exec over"和上面的异常程序没有关系,直接就是所见即所得。

 

 

例子:

[[email protected] ~]# cat error.py

#!/usr/bin/python

a = 0

try:

a

except NameError,e:

print "catch Error:",e

 

print "exec over"

[[email protected] ~]# ./error.py

exec over

解析:

这里的a被定义了,不存在异常,异常程序也就不会有输出,直接就执行异常程序外的语句

 

===============================================================================

try...except的捕获异常分析(一)

例子:可以捕获异常,因为是运行时出现错误

[[email protected] ~]# cat test.py

#!/usr/bin/python

try:

undef

except:

print "catch an except"

[[email protected] ~]# ./test.py

catch an except

解析:

undef是在运行过程中没有被定义的,存在异常,异常程序段中匹配到异常,从而得以输出。

 

 

例子:不能捕获异常,因为是语法错误,运行前出现错误

[[email protected] ~]# cat test.py

#!/usr/bin/python

try:

if undef

except:

print "catch an except"

[[email protected] ~]# ./test.py

  File "./test.py", line 3

    if undef

           ^

SyntaxError: invalid syntax

解析:

先说说python的代码执行过程:在执行异常段程序之前,Python先把代码(.py文件)用解释器编译成二进制的字节码,在此编译过程中会先检查语法结构是否正确,如果语法结构是正确的,就交给字节码虚拟机如果语法结构是错误的,在编译的过程中就会把这个错误给抛出来,然后虚拟机一条一条执行字节码指令,从而完成程序的执行

if undef是语法错误,也就是此异常程序运行之前的。所以异常程序块根本就不会执行,也就不会捕捉到异常。

===============================================================================

try...except的捕获异常分析(二)

 

例子:异常单处理

代码:

[[email protected] ~]# cat firstpy.py

#!/usr/bin/python

try:

    x = input(‘Enter the first number:‘)

    y = input(‘Enter the second number:‘)   

    print x/y

except ZeroDivisionError: #匹配捕获异常和设置异常类型是否一致

    print "Exception: can‘t you enter the denominator is zero" #异常处理快语句

 

代码执行结果

[[email protected] ~]# ./firstpy.py

Enter the first number:10

Enter the second number:0

Exception: can‘t you enter the denominator is zero

解析:

try检测到代码的异常,交给了except进行处理,except将捕获异常和设置异常进行匹配,发现捕获异常的类型和设置异常的类型是一致的,就会执行异常处理块语句。

 

问题来了:

当设置异常的类型是与try:检测出的异常不相同时会出现上面结果呢?

代码:

[[email protected] ~]# cat firstpy.py

#!/usr/bin/python

try:

    x = input(‘Enter the first number:‘)

    y = input(‘Enter the second number:‘)   

    print x/y

except NameError: #匹配捕获异常和设置异常类型是否一致

print "Exception: can‘t you enter the denominator is zero"

结果:

[[email protected] ~]# ./firstpy.py

Enter the first number:10

Enter the second number:0

Traceback (most recent call last):

  File "C:\Users\yu\Desktop\yichang.py", line 3, in <module>

    print x/y

ZeroDivisionError: integer division or modulo by zero

解析:

except开始处理异常时,发现设置异常(NameError)的类型和捕捉异常(ZeroDivisionError)的类型不一致,except就会自动的忽略掉捕捉到的异常,然后将捕捉到的异常向上抛,抛给了python解释器,python解释器会处理这个异常,python解释器处理的默认形式就是终止代码的运行。

 

===============================================================================

try...except的捕获异常分析(三)

 

例子:多个异常处理--捕获多个异常

当捕捉异常与设置异常的类型不相同时,那这个时候,这个异常就会逃过异常的处理并导致程序的终止。那么为了避免出现这个现象,从而捕捉到这个异常,怎么做呢?可以在try/except语句后面加上多个except子句。

 

代码:

[[email protected] ~]# cat firstpy.py

#!/usr/bin/python

try:

    x = input(‘Enter the first number:‘)

    y = input(‘Enter the second number:‘)

    print x/y

except TypeError:

print "Function of the type error"

except ZeroDivisionError:

    print "Exception: can‘t you enter the denominator is zero"

except SyntaxError:

print "Grammar mistakes"

 

执行代码结果:

[[email protected] ~]# ./firstpy.py

Enter the first number:10

Enter the second number:‘2‘   

Function of the type error

Enter the first number:10

Enter the second number:0

Exception: can‘t you enter the denominator is zero

解析:

当捕捉异常与设置异常的类型不相同时,python会终止程序,然后捕捉异常会匹配下一个设置异常的类型是否一致,如果一致,就会输出except的处理块,并且不会继续匹配。如果依旧是不一致的,依然会终止程序,再次进行匹配。

 

问题又来了

1、使用多个except子句是不是很烦

2、怎么能够一次性多匹配内建异常类型呢?

 

例子:匹配多个设置异常---捕获多个异常

代码

[[email protected] ~]# cat firstpy.py

#!/usr/bin/python

try:

    x = input(‘Enter the first number:‘)

    y = input(‘Enter the second number:‘)

    print x/y

except (ZeroDivisionError,TypeError):

    print "Detect abnormalities"

 

代码的执行结果

[[email protected] ~]# ./firstpy.py

Enter the first number:10

Enter the second number:‘1‘        

Detect abnormalities

[[email protected] ~]# ./firstpy.py

Enter the first number:10

Enter the second number:0     

Detect abnormalities

[[email protected] ~]# ./firstpy.py

Enter the first number:10

Enter the second number:/0

Traceback (most recent call last):

  File "./firstpy.py", line 4, in <module>

    y = input(‘Enter the second number:‘)

  File "<string>", line 1

    /0

    ^

SyntaxError: invalid syntax

分析:

想要一次性匹配多个异常类,直接在except后面加上括号,里面写入要匹配的异常类,用逗号隔开。检测异常匹配异常类有两个ZeroDivisionError,TypeError。上述的执行结果有三个,前面连个都被匹配到了,报出了“Detect abnormalities”信息。第三个是没有检测到的,python解释器终止运行。

 

===============================================================================

try...except的捕获异常分析(四)

 

例子:捕捉对象本身

代码

[[email protected] ~]# cat firstpy.py

#!/usr/bin/python

try:

    x = input(‘Enter the first number:‘)

    y = input(‘Enter the second number:‘)

    print x/y

except (ZeroDivisionError,TypeError),e:

    print e

 

结果

[[email protected] ~]# ./firstpy.py

Enter the first number:10

Enter the second number:0

integer division or modulo by zero

[[email protected] ~]# ./firstpy.py

Enter the first number:10

Enter the second number:‘1‘

unsupported operand type(s) for /: ‘int‘ and ‘str‘

 

例子:真正的全力捕捉

  为了避免一些异常没有被检测到,我们不能把所有的异常类型都写下进行匹配,想要实现这个要求,方法很简单,就是在except子句后面什么都不加。

代码:

[[email protected] ~]# cat firstpy.py

#!/usr/bin/python

try:

    x = input(‘Enter the first number:‘)

    y = input(‘Enter the second number:‘)

    print x/y

except (ZeroDivisionError,TypeError),e:

    print e

 

===============================================================================

try ... except...else的捕获异常分析(一)

Python中有很多特殊的else用法,比如用于条件和循环。放到try语句中,其作用其实也差不多:就是当没有检测到异常的时候,则执行else语句。

 

例子:try ... except...else的简单认识

代码:

while True:

    try:

        x = input(‘Enter the first number:‘)

        y = input(‘Enter the second number:‘)

        value = x/y

        print ‘x/y is‘, value

    except: #匹配到异常执行下面的语句

        print ‘please try again‘

    else: #没有匹配到异常就跳出循环

        break

结果

=================RESTART:C:\Users\yu\Desktop\yichang.py=================

>>>

Enter the first number:10

Enter the second number:0

please try again

Enter the first number:10

Enter the second number:‘1‘

please try again

Enter the first number:10

Enter the second number:2

x/y is 5

 

分析:

在循环里只有没有异常引发的情况下才会推出循环,只有异常发生,程序会不断的要求你重新输入。

 

例子:处理信息存储到e

代码

while True:

    try:

        x = input(‘Enter the first number:‘)

        y = input(‘Enter the second number:‘)

        value = x/y

        print ‘x/y is‘, value

    except Exception,e:

        print ‘input:‘,e

        print ‘please try again‘

    else:

        break

结果

==================RESTART:C:\Users\yu\Desktop\yichang.py=================

Enter the first number:10

Enter the second number:0

input: integer division or modulo by zero

please try again

Enter the first number:10

Enter the second number:‘1‘

input: unsupported operand type(s) for /: ‘int‘ and ‘str‘

please try again

Enter the first number:10

Enter the second number:2

x/y is 5

===============================================================================

try ... finally....的捕获异常分析(一)

finally子句是无论是否检测到异常,都会执行的一段代码我们可以丢掉except子句和else子句,单独使用try...finally,也可以配合except等使用。

 

try ... finally语句的基本结构

技术分享 

处理过程:

1、如果try语句没有捕捉到异常,就直接执行do_finally语句块。

2、如果try语句捕捉到了异常,程序首先会执行do_finally语句块,然后将捕捉到的异常交给python解释器处理。

 

例子:存在异常

代码:

x = None

try:

    x = 10/0

finally:

    print ‘Cleaning up.....‘

    del x

解析:

try检测到异常,执行finally子句,然后将捕捉到的异常发给python解释器处理,python解释器会直接终止运行程序。运行这段代码,在程序崩溃之前,对于变量x的清理就完成了

try子句之前初始换x的原因是如果不这样做的话,由于ZeroDIVISIONerror的存在,x就不会被赋值。这样就会导致finally子句中使用del删除他的时候发生异常,而且这个异常是无法捕捉的。

 

结果:

=================RESTART:C:\Users\yu\Desktop\yichang.py==================

Cleaning up.....

 

Traceback (most recent call last):

  File "C:\Users\yu\Desktop\yichang.py", line 3, in <module>

    x = 10/0

ZeroDivisionError: integer division or modulo by zero

 

例子:不存在异常

代码

x = None

try:

    x = 10/2

finally:

    print ‘Cleaning up.....‘

    del x

结果

===================RESTART:C:/Users/yu/Desktop/test.py===================

Cleaning up.....

>>>

解析:

Try语句捕捉到异常,直接执行finally子句块。

 

===============================================================================

try ... except....finally....的捕获异常分析(综合应用)

try ... except....finally的基本结构

技术分享 

try ... except....finally的应用过程

1、try语句没有捕捉到异常,在执行try代码段后,直接执行finaly

2、try捕捉到异常,首先会执行except处理异常,然后执行finally

 

例子:try语句没有捕捉到异常

代码:

x = None

try:

    x = 10/2

except ZeroDivisionError:

    print "Exception: can‘t you enter the denominator is zero"

finally:

    print ‘Cleaning up.....‘

    del x

 

结果:

=================RESTART:C:/Users/yu/Desktop/except.py=================

Cleaning up.....

 

分析:

这里没有捕捉到异常,直接执行了finally语句

 

例子:try语句捕捉到了异常

代码:

x = None

try:

    x = 10/0

except ZeroDivisionError:

    print "Exception: can‘t you enter the denominator is zero"

finally:

    print ‘Cleaning up.....‘

    del x

 

 

结果:

=================RESTART:C:/Users/yu/Desktop/except.py=================

Exception: can‘t you enter the denominator is zero

Cleaning up.....

 

分析

这里捕捉到了异常。(捕捉异常与设置异常类型一致)先是执行except语句,然后执行finally语句。

 

===============================================================================

With语句的捕获异常分析(综合应用)

With语句的基本结构

技术分享 

With语句的使用过程

1、with语句用来代替try...except...finally语句,是代码更加简洁

2、context表达式返回的是一个上下文管理器对象

3、var用来保存context返回对象。var可以是单个变量,或者由“()”括起来的元组(不能是仅仅由“,”分隔的变量列表,必须加“()”)

4、with_suite 使用var变量来对context返回对象进行操作

with语句实质是上下文管理:

1上下文管理协议:包含方法 __enter__() __exit__(),支持该协议的对象要实现这两个方法。

2上下文管理器:支持上下文管理协议的对象,这种对象实现了__enter__() __exit__() 方法。上下文管理器定义执行 with 语句时要建立的运行时上下文,负责执行 with 语句块上下文中的进入与退出操作。通常使用 with 语句调用上下文管理器,也可以通过直接调用其方法来使用。

3运行时上下文:由上下文管理器创建,通过上下文管理器的 __enter__()

__exit__() 方法实现,__enter__() 方法在语句体执行之前进入运行时上下文,__exit__() 在语句体执行完后从运行时上下文退出with 语句支持运行时上下文这一概念。

4上下文表达式:with 语句中跟在关键字 with 之后的表达式,该表达式要返回一个上下文管理器对象。

5语句体(with-body):with 语句包裹起来的代码块,在执行语句体之前会调用上下文管理器的 __enter__() 方法,执行完语句体之后会执行 __exit__() 方法。

 

 

例子:with语句实例

技术分享 

分析:

1、打开1.txt文件

2、打开文件后,open(‘1.txt’)语句会返回一个对象,将这些对象保存在f

3、With中的代码执行完成后,就关闭文件。如果代买执行时出现异常,首先管关闭文件,然后在进程处理异常。

 

代码:使用 with 语句操作文件对象

    with open(r‘somefileName‘) as somefile:

        for line in somefile:

            print line

            # ...more code

分析:

这里使用了 with 语句,不管在处理文件过程中是否发生异常,都能保证 with 语句执行完毕后,被打开的文件句柄已经关闭了。如果使用传统的 try/finally 范式,则要使用类似如下代码:

 

代码:try/finally 方式操作文件对象

    somefile = open(r‘somefileName‘)

    try:

        for line in somefile:

            print line

            # ...more code

    finally:

        somefile.close()

分析:

比较起来,使用 with 语句可以减少编码量。已经加入对上下文管理协议支持的还有模块 threadingdecimal 等。

 

 

 

例子:with 语句执行过程

    context_manager = context_expression

    exit = type(context_manager).__exit__  

    value = type(context_manager).__enter__(context_manager)

    exc = True   # True 表示正常执行,即便有异常也忽略;False 表示重新抛出异常,需要对异常进行处理

    try:

        try:

            target = value  # 如果使用了 as 子句

            with-body     # 执行 with-body

        except:

            # 执行过程中有异常发生

            exc = False

            # 如果 __exit__ 返回 True,则异常被忽略;如果返回 False,则重新抛出异常

            # 由外层代码对异常进行处理

            if not exit(context_manager, *sys.exc_info()):

                raise

    finally:

        # 正常退出,或者通过 statement-body 中的 break/continue/return 语句退出

        # 或者忽略异常退出

        if exc:

            exit(context_manager, None, None, None)

        # 缺省返回 NoneNone 在布尔上下文中看做是 False

过程分析:

1执行 context_expression,生成上下文管理器 context_manager

2调用上下文管理器的 __enter__() 方法;如果使用了 as 子句,则将 __enter__() 方法的返回值赋值给 as 子句中的 target(s)

3执行语句体 with-body

4不管是否执行过程中是否发生了异常,执行上下文管理器的 __exit__() 方法,__exit__() 方法负责执行清理工作,如释放资源等。如果执行过程中没有出现异常,或者语句体中执行了语句 break/continue/return,则以 None 作为参数调用 __exit__(None, None, None) ;如果执行过程中出现异常,则使用 sys.exc_info 得到的异常信息为参数调用 __exit__(exc_type, exc_value, exc_traceback)

5出现异常时,如果 __exit__(type, value, traceback) 返回 False,则会重新抛出异常,让with 之外的语句逻辑来处理异常,这也是通用做法;如果返回 True,则忽略异常,不再对异常进行处理.

 

总结

with是对try…expect…finally语法的一种简化,并且提供了对于异常非常好的处理方式。在Python2种方式来实现with语法:class-baseddecorator-based2种方式在原理上是等价的,可以根据具体场景自己选择。

 

 

三:raiseassert语句

===============================================================================

---------raise语句

Raise语句用于主动跑出异常,从而结束异常。

例子:

>>> a = 10

>>> b = 0

>>> raise a/b

 

Traceback (most recent call last):

  File "<pyshell#28>", line 1, in <module>

    raise a/b

ZeroDivisionError: integer division or modulo by zero

 

===============================================================================

----------assert语句

1assert语句用来声明某个条件是真的。

2、如果你非常确信某个你使用的列表中至少有一个元素,而你想要检验这一点,并且在它非真的时候引发一个错误,那么assert语句是应用在这种情形下的理想语句。

3、当assert语句失败的时候,会引发一AssertionError

例子:

>>> list1 = [‘information‘,‘Genal‘,‘23‘,‘man‘]

>>> len(list1)

4

>>> assert len(list1) > =4 #判定list1中元素大于等于4个的,判定为真,

>>> list1.pop()

‘man‘

>>> len(list1)

3

>>> assert len(list1) > =4

 

Traceback (most recent call last):#判定list1中元素大于等于4个的,判定为假。

 

  File "<pyshell#23>", line 1, in <module>

    assert len(list1) > 3

AssertionError

 

四:标准异常和自定义异常

===============================================================================

----------标准异常

技术分享 

 

 

 

----------自定义异常

自定义异常:

1、Python允许自定义异常,用于描述python中没有涉及的异常情况

2、自定义异常必须继承Exception

3、自定义异常只能主动触发

 

自定义异常示例:

技术分享 

例子:

>>> class FileError(IOError):

pass

 

>>> raise FileError,"Test FileError"

 

Traceback (most recent call last):

  File "<pyshell#36>", line 1, in <module>

    raise FileError,"Test FileError"

FileError: Test FileError

 

 

例子:

>>> try:

raise FileError,"Test FileError"

except FileError,e:

print e

Test FileError

 

例子:

代码:

class CustomError(Exception):

    def _init_(self,info):

        Exception,_init_(self)

        self,errorinfo = info

 

    def _str_(self):

        return "CustionError:%s" % self,errorinfo

try:

    raise CustomError("test CustomError")

except CustomError,e:

    print "ErrorInfo:%s" %(e)

结果

================= RESTART: C:/Users/yu/Desktop/exception2.py =================

ErrorInfo:test CustomError

>>>

 



本文出自 “末班车” 博客,请务必保留此出处http://blxueyuan.blog.51cto.com/9673381/1877663

以上是关于Python初级009-错误与异常的主要内容,如果未能解决你的问题,请参考以下文章

Python函数初级

Python初级008-面向对象

初级Python

python初级(302) 4 函数

[Python]_[初级]_[使用PyCharm时不识别根包位置和Debug时报ModuleNotFoundError错误]

[Python]_[初级]_[使用PyCharm时不识别根包位置和Debug时报ModuleNotFoundError错误]