Python——异常

一. 什么是异常

1.  异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行。 

2. 一般情况下,Python无法正常处理程序时就会发生一个异常。

3.  异常是 Python 对象,表示一个错误。当 Python 脚本发生异常时我们需要捕获处理它,否则程序会终止执行。

4. 每一个异常都是一些类的实例,这些实例可以被引用,并且可以用很多种方法进行捕捉,使得错误可以被处理,而不是让整个程序失败

 

二.  异常处理

处理程序中的异常,最简单的是使用  try  语句处理。

try 语句的基本形式是  try/execpt。

try / except  语句用来检测  try  语句块中的错误,从而让 except  语句捕获异常信息并处理。如果你不想在异常发生时结束你的程序,只需在try里捕获它。

语法如下:
 

try:
<语句>                         #运行的代码(需要检测的语句)
 
except <名字>:          #发生异常时的操作。名字为对应错误的名称
<语句>  

 

1、try的工作原理是,当开始一个try语句后,python就在当前程序的上下文中作标记,这样当异常出现时就可以回到做标记的地方。

2、try子句先执行,接下来会发生什么依赖于执行时是否出现异常。如果当try后的语句执行时发生异常,python就跳回到try并执行第一个匹配该异常的except子句每一个try,都必须至少有一个except。异常处理完毕,控制流就通过整个try语句(除非在处理异常时又引发新的异常)。

3、如果在try后的语句里发生了异常,却没有匹配的except子句,异常将被递交到上层的try,或者到程序的最上层(这样将结束程序,并打印缺省的出错信息)。

4、如果在try子句执行时没有发生异常,python将执行else语句后的语句(如果有else的话),然后控制流通过整个try语句。

5、当我们认为某些代码可能会出错时,就可以用try来运行这段代码,如果执行出错,则后续代码不会继续执行,而是直接跳转至错误处理代码,即except语句块,执行完except后,如果有finally语句块,则执行finally语句块

6、在try程序段中,我们放入容易犯错的部分。我们可以跟上except,来说明如果在try部分的语句发生错误时,程序该做的事情。如果没有发生异常,则except部分被跳过

 

def exp (x,y):
    try:
        a = x/y
        print('a='.a)
        return a
    except Exception:
        print('程序出现异常,异常信息:被除数为  0')


exp(2, 0)

执行结果:

程序出现异常,异常信息:被除数为  0

 

三.  抛出异常

1、如果只想知道是否抛出了异常,并不想处理,使用一个简单的raise语句就可以再次把异常抛出。一旦执行了 raise 语句,raise后面的语句将不能执行。 

2、用 raise 语句来引发一个异常。异常/错误对象必须有一个名字,且它们应是 Error 或 Exception 类的子类

3、raise关键字后面需要指定你抛出的异常类型为了能够捕获异常,"except"语句必须有用相同的异常来抛出类对象或者字符串。

raise语法格式如下:

raise [ Exception [, args [, traceback] ] ]

  • 语句中 Exception 是异常的类型(例如,NameError)参数标准异常中任一种,args 是自已提供的异常参数。最后一个参数是可选的(在实践中很少使用),如果存在,是跟踪异常对象。
  • 格式:raise 异常名称(‘异常描述’)
>>> raise Exception
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
Exception
>>>
>>> raise NameError('This is NameError')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: This is NameError

 

 

如果只想知道是否抛出了,并不想处理,使用一个简单的  raise  语句就可以再次把异常抛出。

这个是把最近一次产生的异常重新抛出来,交给上层 (我已经知道了这个异常并且捕获到了,但是我不处理,而由我的上层调用处理)

1、异常会在捕获之后再次触发同一个异常。

2、如果要捕获异常后要重复抛出,请使用raise,后面不要带任何参数或信息

3、except语句不是必须的,finally语句也不是必须的,但是二者必须要有一个,否则就没有try的意义了。

 

>>> try :
...     raise NameError('This is NameError')
... except NameError:
...     print(' An exception happened!')        # 后面不加 raise
...
 An exception happened!
>>>
>>>
>>> try :
...     raise NameError('This is NameError')
... except NameError:
...     print(' An exception happened!')        
...     raise                                   # 后面加一个 raise
...
 An exception happened!
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
NameError: This is NameError

raise关键字后面是抛出是一个通用的异常类型(Exception),一般来说抛出的异常越详细越好,Python在exceptions模块内建了很多的异常类型,通过使用dir函数来查看exceptions中的异常类型。

 

Python  重要的内建异常类
异常名称描述
Exception常规错误的基类
AttributeError对象没有这个属性
IOError

输入/输出操作失败

IndexError序列中没有此索引
KeyError映射中没有这个键
NameError未申明/初始化对象(没有属性)
SyntaxErrorPython  语法错误
SystemError一般解释器系统错误
ValueError传入无效的参数

 

四.  捕获多个异常

try:
<语句>        #运行别的代码
 
except <名字>:
<语句>        #如果在try部分引发了'name1'异常
 
except <名字>,<数据>:
<语句>         #如果引发了'name2'异常,获得附加的数据

 

首先,执行 try 子句 ( 在关键字  try  和关键字  except 之间的语句)。如果没有发生异常,忽略  except 子句,try 子句执行后结束。如果在执行  try 子句的过程中发生异常,try  子句余下的部分就会被忽略。如果异常的类型和 except 之后的名称相符,对应的  except 子句就会被执行。最后执行  try  语句之后的代码。如果一个异常没有与任何 except  匹配,这个异常就会传递到上层的 try 中。一个  try  语句可能包含多个  except  子句,分别处理不同的异常,但最多只有一个分支会被执行。

处理程序将只针对对应 try子句中的异常进行处现,而不会处理其他异常语句中的异常

def exp (x,y):
    try:
        a = x/y
        b  = name 
    except ZeroDivisionError:
        print("this is ZeroDivisionErro")
    except NameError:
        print("this is NameError")


exp(2, 0)

执行结果:

this is ZeroDivisionErro

 

五. 使用一个块捕捉多个异常

 

如果需要使用一个块捕捉多个类型异常,可以将异常类型作为元组列出。使用该方式时,遇到的异常类型是元组中的任意一个,都会走异常流程。

def exp (x,y):
    try:
        a = x/y
        b  = name 
    except (ZeroDivisionError,NameError,TypeError):
        print("one of ZeroDivisionError  or  NameError  or TypeError")
   

exp(2, 0)

执行结果:

one of ZeroDivisionError  or  NameError  or TypeError

 

六. 捕捉对象

如果希望在except字句中访问异常对象本身,也就是看到一个异常对象真正的异常信息,而不是输出自己定义的异常信息,可以使用as e的形式,称之为捕捉异常。

def exp (x,y):
    try:
        a = x/y
        b  = name 
    except (ZeroDivisionError,NameError,TypeError) as e :
        print(e)
   

exp(2, 0)

执行结果:

division by zero
def exp (x,y):
    try:
         b  = name 
         a = x/y
       
    except (ZeroDivisionError,NameError,TypeError) as e :
        print(e)
   

exp(2, 0)

执行结果:

name 'name' is not defined

 

七 .  全捕捉

#!/usr/bin/python3
# -*- coding:UTF-8 -*-

def exp (x,y):
    try:
         
         a = x/y
         b  = name 
    except (ZeroDivisionError,NameError,TypeError) as e :
        print(e)
   

exp(2, '')

执行结果:

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

 

由上面可以看出即使程序能自动处理很多种异常,但是还是会有部分异常会被遗漏(逃过了try\except的检查)。在这种情况下,与其使用异常捕捉的  try\except  语句隐藏异常,还不如让程序立即崩溃

#!/usr/bin/python3
# -*- coding:UTF-8 -*-

def exp (x,y):
    try:
         a = x/y
         b  = name 
    except  :
        print(" Error happenend")
   

exp(2, '')

执行结果:

 Error happenend

1、由上面例子可以看出,可以在except子句中忽略所有异常类,从而让程序输出自己定义的异常信息

2、从实用性方面来讲,不建议这么做,因为这样会隐藏所有的的异常,从而不好找到问题。建议使用抛出异常的方式处理

 

八.  异常中的 else

try:
<语句>        #运行别的代码
 
except <名字>:
<语句>        #如果在try部份引发了'name1'异常
 
except <名字>,<数据>:
<语句>        #如果引发了'name2'异常,获得附加的数据
 
else:
<语句>        #如果没有异常发生

 

如果在 try  子句执行时没有发生异常,就会执行 else 语句后的语句。

使用 else 子句可以避免一些意想不到而  except 又没有捕获的异常。

#!/usr/bin/python3
# -*- coding:UTF-8 -*-

def exp (x,y):
    try:
         a = x/y
        
    except  :
        print(" Error happenend")
    else:
        print("it went as except")
    
    print(a)
   

exp(2, 1)

执行结果:

it went as except
2.0

 

九.   finally 子句

python  中的  finally 子句需要和  try  子句一起使用,组成  try / finally  的语句形式,try / finally  语句表示无论发生异常与否都将执行最后的代码

#!/usr/bin/python3
# -*- coding:UTF-8 -*-

def exp (x,y):
    try:
         a = x/y
    finally:
        print("no matter what happened,i will show in front of you")

exp(2, 0)

执行结果:

pydev debugger: starting (pid: 6256)
no matter what happened,i will show in front of you
Traceback (most recent call last):
  File "C:\eclipse_JavaFX\plugins\org.python.pydev.core_6.4.3.201807050139\pysrc\pydevd.py", line 1715, in <module>
    main()
  File "C:\eclipse_JavaFX\plugins\org.python.pydev.core_6.4.3.201807050139\pysrc\pydevd.py", line 1709, in main
    globals = debugger.run(setup['file'], None, None, is_module)
  File "C:\eclipse_JavaFX\plugins\org.python.pydev.core_6.4.3.201807050139\pysrc\pydevd.py", line 1062, in run
    return self._exec(is_module, entry_point_fn, module_name, file, globals, locals)
  File "C:\eclipse_JavaFX\plugins\org.python.pydev.core_6.4.3.201807050139\pysrc\pydevd.py", line 1069, in _exec
    pydev_imports.execfile(file, globals, locals)  # execute the script
  File "C:\eclipse_JavaFX\plugins\org.python.pydev.core_6.4.3.201807050139\pysrc\_pydev_imps\_pydev_execfile.py", line 25, in execfile
    exec(compile(contents+"\n", file, 'exec'), glob, loc)
  File "D:\Users\li_yx\workspace\pythontest\pytest.py", line 10, in <module>
    exp(2, 0)
  File "D:\Users\li_yx\workspace\pythontest\pytest.py", line 6, in exp
    a = x/y
ZeroDivisionError: division by zero

 

try / finally语句也可以和except、else一起组合使用。但要记得  else在except  之后,finally 在 except和else 之后(这种组合中except的作用为:用于截获可能发生的异常,使得程序不报错而执行except所属语句)

#!/usr/bin/python3
# -*- coding:UTF-8 -*-

def exp (x,y):
    try:
         a = x/y
    except Exception as e:
        print(e)
    finally:
        print("no matter what happened,i will show in front of you")

exp(2, 0)

执行结果:

division by zero
no matter what happened,i will show in front of you

 

十.  自定义异常

1、python允许程序员自定义异常,用于描述python中没有涉及的异常情况,自定义异常必须继承 Exception类,自定义异常按照命名规范以"Error"结尾,显示地告诉程序员这是异常。自定义异常使用raise语句引发,而且只能通过人工方式触发。

2、因为错误就是类捕获一个错误就是捕获该类的一个实例,因此错误并不是凭空产生的,而是由一些不合理的部分导致的。python的内置函数会抛出很多类型的错误,我们自己编写的函数也可以抛出错误。如果要抛出错误,那么可以根据需要定义一个错误的类,选择好继承关系,然后用raise语句抛出一个错误的实例

#!/usr/bin/python3
# -*- coding:UTF-8 -*-

class MyError(Exception):
    def __init__(self):
        pass
    
    def __str__(self):
        return ('this is self define error')
    
    
def my_error_test():
    try:
        raise MyError()
    except MyError as e:
        print("exception inof:",e)
        
my_error_test()

执行结果:

exception inof: this is self define error

 

十一.  异常和函数

如果异常在函数内引发而不被处理,就会传播至函数调用的地方。如果异常在调用的地方还是没有被处理,则会继续传播,一直到达主程序。如果在主程序也没有做异常处理,异常就会被python解释器捕获,输出一个错误信息,然后退出程序

def division_fun(x,y):
    return x/int(y)

def exp_fun(x,y):
    return division_fun(x, y) * 10

def main(x,y):
    exp_fun(x, y)
    

main(2, 0)

执行结果:

pydev debugger: starting (pid: 10936)
Traceback (most recent call last):
  File "C:\eclipse_JavaFX\plugins\org.python.pydev.core_6.4.3.201807050139\pysrc\pydevd.py", line 1715, in <module>
    main()
  File "C:\eclipse_JavaFX\plugins\org.python.pydev.core_6.4.3.201807050139\pysrc\pydevd.py", line 1709, in main
    globals = debugger.run(setup['file'], None, None, is_module)
  File "C:\eclipse_JavaFX\plugins\org.python.pydev.core_6.4.3.201807050139\pysrc\pydevd.py", line 1062, in run
    return self._exec(is_module, entry_point_fn, module_name, file, globals, locals)
  File "C:\eclipse_JavaFX\plugins\org.python.pydev.core_6.4.3.201807050139\pysrc\pydevd.py", line 1069, in _exec
    pydev_imports.execfile(file, globals, locals)  # execute the script
  File "C:\eclipse_JavaFX\plugins\org.python.pydev.core_6.4.3.201807050139\pysrc\_pydev_imps\_pydev_execfile.py", line 25, in execfile
    exec(compile(contents+"\n", file, 'exec'), glob, loc)
  File "D:\Users\li_yx\workspace\pythontest\pytest.py", line 11, in <module>
    main(2, 0)
  File "D:\Users\li_yx\workspace\pythontest\pytest.py", line 8, in main
    exp_fun(x, y)
  File "D:\Users\li_yx\workspace\pythontest\pytest.py", line 5, in exp_fun
    return division_fun(x, y) * 10
  File "D:\Users\li_yx\workspace\pythontest\pytest.py", line 2, in division_fun
    return x/int(y)
ZeroDivisionError: division by zero

 

【注】异常信息是以堆栈的形式被抛出的,因而是从下往上查看。

 

十二.  assert  语句触发异常

assert 语句根据后面的表达式的真假来控制程序流。若为True,则往下执行。若为 False,则中断程序并调用默认的异常处理器,同时输出指定的提示信息。 

格式:

assert   expression , 'information'
 

>>> def testAssert(x):
...     assert x<1 , 'Invalid value'
...     print(' No Error')
...
>>>
>>> testAssert(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in testAssert
AssertionError: Invalid value
>>>
>>>
>>> testAssert(0)
 No Error

 

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值