python基础教程:错误处理和异常处理(二)

码途星河引
• 阅读 1038

前面我们讲到的Python编程过程中,在可能出现异常的地方使用尝试语句,来正确的处理一些异常,可以保证程序不中断继续运行。

python基础教程:错误处理和异常处理(二)

抛出异常

有时候,我们可能需要在程序的某些地方主动抛出异常,通知调用该代码的程序有错误发生这时候,我们就要用到。raise语句。raise语句就是帮助我们抛出知道异常的,比如:

In [6]: raise NameError("Bad Name")
-----------------------------------
NameError           Traceback (most recent call last)
<ipython-input-6-966a00c8f456> in <module>
----> 1 raise NameError("Bad Name")

NameError: Bad Name

raise的使用很简单,它的语法如下:

raise [expression [from expression]]

如果它后面不带表达式(参数),它会重新引发当前作用域内最后一个激活的异常。如果当前作用域内没有激活的异常,将会引发RuntimeError来提示错误。

如果后面带有表达式,则将表达式求值为要抛出的异常对象,该表达式必须是一个异常实例或者是一个异常类(自继承BaseException类)。如果它是一个异常类,它将通过调用没有参数的构造函数来隐式实例化:

raise NameError  # 等同于 'raise NameError()'

raise后面表达式还可以跟一个from¸...。,用于异常的串联。from子句的表达式必须是另一个异常或实例,它将作为可写的(可写入的)的__cause__属性被关联到所引发的异常。如果引发的异常未被捕捉处理,两个异常都将被打印出来:

In [9]: try: 
   ...:     print(10/0) 
   ...: except Exception as e: 
   ...:     raise RuntimeError("something is wrong") from e 
   ...:
----------------------------------------------------------
ZeroDivisionError            Traceback (most recent call last)
<ipython-input-9-7de64aad634f> in <module>
      1 try:
----> 2     print(10/0)
      3 except Exception as e:

ZeroDivisionError: division by zero

The above exception was the direct cause of the following exception:

RuntimeError                 Traceback (most recent call last)
<ipython-input-9-7de64aad634f> in <module>
      2     print(10/0)
      3 except Exception as e:
----> 4     raise RuntimeError("something is wrong") from e
      5 

RuntimeError: something is wrong

如果异常一个在except[主语]或finally[主语]中被抛出,类似的机制会隐式地发挥作用,的之前将异常关联被新到异常的__context__属性例如:

In [10]: try: 
    ...:     print(10/0) 
    ...: except: 
    ...:     raise RuntimeError("something is wrong") 
    ...:
-----------------------------------------------
ZeroDivisionError           Traceback (most recent call last)
<ipython-input-10-e950a6292482> in <module>
      1 try:
----> 2     print(10/0)
      3 except:

ZeroDivisionError: division by zero

During handling of the above exception, another exception occurred:

RuntimeError                Traceback (most recent call last)
<ipython-input-10-e950a6292482> in <module>
      2     print(10/0)
      3 except:
----> 4     raise RuntimeError("something is wrong")
      5 

RuntimeError: something is wrong

串连异常柯林斯通过在from[主语]中用None来显示地禁止:

In [11]: try: 
    ...:     print(10/0) 
    ...: except: 
    ...:     raise RuntimeError("something is wrong") from None 
    ...:
-------------------------------
RuntimeError                   Traceback (most recent call last)
<ipython-input-11-1818bd8b9d31> in <module>
      2     print(10/0)
      3 except:
----> 4     raise RuntimeError("something is wrong") from None
      5 

RuntimeError: something is wrong

用户自定义异常

Python的允许用户自定义异常类,应该通常直接或间接地继承自Exception类。

自定义的异常类的名称通常以“错误”结尾,类似与内置标准异常的命名。自定义的异常类,可以像其它类那样可以执行任何操作,但通常保持简单,只提供用以处理程序为异常提取有关错误信息的属性为模块自定义多个不同错误的异常时,通常是为该模块定义一个异常基类,再为不同错误创建特定的子类例如。:

class ModuleError(Exception):
    '''模块的异常基类'''
    pass

class ModuleNameError(ModuleError):
    '''模块的特定异常子类'''
    pass

class ModuleValueError(ModuleError):
    '''模块的另一个特定异常子类'''
    pass

最后的清理操作:finally子句

finally的英文[主语] try语句的一个可选[主语],用于定义在任何情况下都执行的操作,叫做“清理操作”例如:

In [12]: try: 
    ...:     raise NameError 
    ...: finally: 
    ...:     print('Bye :)') 
    ...:      
    ...:
Bye :)
-------------------------------
NameError        Traceback (most recent call last)
<ipython-input-12-9cda1523ce81> in <module>
      1 try:
----> 2     raise NameError
      3 finally:
      4     print('Bye :)')
      5 

NameError: 

finally子句总会在离开try语句前被执行,无论发生异常与否。当在try子句中发生了异常且尚未被except子句处理(或者它发生在除或其他子句中)时,该异常将在终子句执行后被重新抛出。当try语句的任何其他子句通过break,continue或return语句离开时,最后也会在“离开之前”被执行,参考下面这个更复杂的例子:

In [13]: def divide(a, b): 
    ...:     try: 
    ...:         result = a / b 
    ...:     except ZeroDivisionError: 
    ...:         print('divided by zero!') 
    ...:     else: 
    ...:         print('result is', result) 
    ...:     finally: 
    ...:         print('leaving try') 
    ...:

In [14]: divide(8, 2)
result is 4.0
leaving try

In [15]: divide(8, 0)
divided by zero!
leaving try

In [16]: divide('a', 2)
leaving try
-----------------------
TypeError              Traceback (most recent call last)
<ipython-input-16-324d9fa22da2> in <module>
----> 1 divide('a', 2)

<ipython-input-13-5e4380c62566> in divide(a, b)
      1 def divide(a, b):
      2     try:
----> 3         result = a / b
      4     except ZeroDivisionError:
      5         print('divided by zero!')

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

从上面的例子我们看到,finally子句总是会被执行。字符串但被除时引发了TypeError的异常,异常这个没有被except¸...。处理,在就会finally¸...。执行后被重新抛出。

在编程实践中,finally子句对释放文件或网络连接等外部资源是非常有用的。

总结

编程中,我们不仅要在恰当的地方处理异常,也要在必要的时候抛出异常,我们抛出异常时可以自定义异常。熟练运用异常可以使我们的程序更加健壮,别忘了必要的时候使用finally来释放外部资源。

点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
3年前
STM32 中断详解
中断,在单片机中占有非常重要的地位。代码默认地从上向下执行,遇到条件或者其他语句,会按照指定的地方跳转。而在单片机执行代码的过程中,难免会有一些突发的情况需要处理,这样就会打断当前的代码,待处理完突发情况之后,程序会回到被打断的地方继续执行。1EXTI控制器外部中断/事件控制器(EXTI)管理了控制器的23个中断/事件线。每
梦
4年前
微信小程序new Date()转换时间异常问题
微信小程序苹果手机页面上显示时间异常,安卓机正常问题image(https://imghelloworld.osscnbeijing.aliyuncs.com/imgs/b691e1230e2f15efbd81fe11ef734d4f.png)错误代码vardate'2021030617:00:00'vardateT
Gwendolyn62 Gwendolyn62
4年前
python中的异常处理
异常异常就是程序运行时发生错误的信号,在python中,错误触发的异常如下异常种类  在python中不同的异常可以用不同的类型(python
Stella981 Stella981
3年前
Python从入门到入土
异常处理tryexcept在Python中,异常处理,主要是tryexcept语句,通常语法格式如下.try:代码块1exceptExceptionase:print(e)代码2try语句按照如下方式工作;首先,执行try子句(在关键字try和关键字except之间的语句)如果没有异常
Stella981 Stella981
3年前
Python异常捕获与处理
一、任务描述  本实验任务主要对Python异常进行一些基本操作,通过完成本实验任务,要求学生熟练掌握Python异常的基本操作。并对异常的基本操作进行整理并填写工作任务报告。二、任务目标1、掌握Python异常的捕获2、掌握Python异常的处理三、任务环境Ubuntu16.04、Python2.7
Wesley13 Wesley13
3年前
初探 Objective
作者:Cyandev,iOS和MacOS开发者,目前就职于字节跳动0x00前言异常处理是许多高级语言都具有的特性,它可以直接中断当前函数并将控制权转交给能够处理异常的函数。不同语言在异常处理的实现上各不相同,本文主要来分析一下ObjectiveC和C这两个语言。为什么要把ObjectiveC和
Wesley13 Wesley13
3年前
Java异常
异常分为两种:Exception、ErrorException:异常,可以捕捉到,进行处理以后可以让程序继续正常执行Error:错误,不能捕捉,只能修改代码,重新执行ThrowableException(RuntimeException非运行时异常)throw:抛出指定的异常throws:用在方法声明处,声明该方法可能发生
Easter79 Easter79
3年前
SpringBoot2.0系列教程(五)Springboot框架添加全局异常处理
Hello大家好,本章我们添加全局异常处理。另求各路大神指点,感谢一:为什么需要定义全局异常在互联网时代,我们所开发的应用大多是直面用户的,程序中的任何一点小疏忽都可能导致用户的流失,而程序出现异常往往又是不可避免的,所以我们需要对异常进行捕获,然后给予相应的处理,来减少程序异常对用户体验的影响二:添加业务类异常在前面说过
Wesley13 Wesley13
3年前
Java 异常处理
完善的异常处理有利于程序稳定。不要不停的catch异常。什么是异常??定义:异常是一个事件,它发生在程序的执行过程中,会破坏程序的正常执行在一个错误发生会在一个方法时,创建一个Exception对象来处理来保证程序能继续执行下去。当异常发生时,JVM会搜索调用栈上的所有方法,若没有找到合适的异常处理方法,JVM将会终
Stella981 Stella981
3年前
SpringBoot2.0系列教程(五)Springboot框架添加全局异常处理
Hello大家好,本章我们添加全局异常处理。另求各路大神指点,感谢一:为什么需要定义全局异常在互联网时代,我们所开发的应用大多是直面用户的,程序中的任何一点小疏忽都可能导致用户的流失,而程序出现异常往往又是不可避免的,所以我们需要对异常进行捕获,然后给予相应的处理,来减少程序异常对用户体验的影响二:添加业务类异常在前面说过
小万哥 小万哥
2年前
C++异常和错误处理机制:如何使您的程序更加稳定和可靠
在C编程中,异常处理和错误处理机制是非常重要的。它们可以帮助程序员有效地处理运行时错误和异常情况。本文将介绍C中的异常处理和错误处理机制。什么是异常处理?异常处理是指在程序执行过程中发生异常或错误时,程序能够捕获并处理这些异常或错误的机制。例如,当