使用Python进行异常处理

  • 来源 | 愿码(ChainDesk.CN)内容编辑
  • 愿码Slogan | 链接每一个程序员的故事
  • 网站 | http://chaindesk.cn
  • 愿码愿景 | 打造全学科IT系统免费课程,助力小白用户、初级工程师0成本免费系统学习、低成本进阶,帮助BAT一线资深工程师成长并利用自身优点创造睡后收入。
  • 官方公众号 | 愿码 | 愿码服务号 | 区块链部落
  • 免费加入愿码全思惟工程师社群 | 任一公众号回复“愿码”两个字获取入群二维码

本文阅读时长:10minpython

本文所涉及知识点程序员

  • Python中有哪些异常 ?
  • 使用try ... except子句控制程序流
  • 经过处理异常来处理常见问题
  • 建立和使用自定义异常类

在直接进入代码并解决这些问题以前,让咱们首先了解异常是什么以及处理异常是什么意思。数据库

什么是异常?


异常是Python中的对象。它为咱们提供了有关在程序执行期间检测到的错误的信息。在调试应用程序时注意到的错误是未处理的异常,由于咱们没有这些异常。在本文后面,您将学习处理这些异常的技巧。函数

在早期回溯中看到的ValueError和IndexError异常是Python中内置异常类型的示例 。在下一节中,您将了解Python支持的其余一些内置异常 。学习

最多见的异常


让咱们快速回顾一些最常遇到的异常。最简单的方法是尝试运行一些错误的代码,让它报告错误回溯的问题!启动Python解释器并编写如下代码:区块链

如下是一些异常状况:测试

正如您所看到的,代码的每一行都会抛出一个带有异常类型的错误回溯(突出显示)。这些是Python中的一些内置异常。Python提供BaseException做为全部内置异常的基类。可是,大多数内置异常不直接继承BaseException。相反,它们是从一个名为Exception的类派生而来的,而这个类又继承自BaseException。处理程序退出的内置异常(例如,SystemExit)直接从BaseException派生。您还能够建立本身的异常类做为Exception的子类。您将在本文后面了解到这一点。网站

异常处理

到目前为止,咱们已经看到了异常的发生方式 如今,是时候学习如何使用try ... except子句来处理这些异常。如下伪代码显示了try ... except子句的一个很是简单的示例:spa

咱们来看看前面的代码片断:调试

· 首先,程序尝试执行try子句中的代码。

· 在执行期间,若是出现错误(若是发生异常),它将跳出此try子句。try块中的其他代码不会被执行。

· 而后,它在except子句中查找适当的异常处理程序并执行它。

这里使用的 except子句是通用的。它将捕获try子句中发生的全部类型的异常。而不是拥有这个“全能”处理程序,更好的作法是捕获您预期的错误并编写特定于这些错误的异常处理代码。例如,try子句中的代码可能会抛出AssertionError。您能够编写特定的异常处理程序,而不是使用universal except子句,以下所示:

在这里,咱们有一个except子句专门处理AssertionError。它还意味着除了AssertionError以外的任何错误都将做为未处理的异常漏掉。为此,咱们须要使用不一样的异常处理程序定义多个except子句。可是,在任什么时候候,只会调用一个异常处理程序。用一个例子能够更好地解释这一点。咱们来看看下面的代码片断:

该试块调用solve_something() 。此函数接受一个数字做为用户输入,并断言该数字大于零。若是断言失败,它会直接跳转处处理程序,但AssertionError除外。

在另外一个场景中,若是> 0,则执行solve_something()中的其他代码。您会注意到未定义变量x,这会致使NameError。此异常由另外一个异常子句处理,但NameError除外。一样,您能够为预期的错误定义特定的异常处理程序。

提升并从新提出异常


Python中的raise关键字用于强制发生异常。换句话说,它引起了一个异常。语法很简单; 只需打开Python解释器并输入:

>>> raise AssertionError("some error message")

这会产生如下错误回溯:

Traceback (most recent call last): 
  File "", line 1, in 
AssertionError :  some error message

在某些状况下,咱们须要从新引起异常。假设,在try子句中,您有一个将数字除以零的表达式。在普通算术中,这个表达没有意义。这是一个错误!这会致使程序引起一个名为ZeroDivisionError的异常。若是没有异常处理代码,程序将只打印错误消息并终止。

若是您但愿将此错误写入某个日志文件而后终止该程序,该怎么办?在这里,您可使用except子句首先记录错误。而后,使用不带任何参数的raise关键字来从新引起异常。异常将在堆栈中向上传播。在此示例中,它终止程序。可使用raise关键字从新引起异常而不使用任何参数。

这是一个示例,显示如何从新引起异常:

能够看出,在解决a / b表达式时,会出现zeroexception的adivision。这是由于变量b的值设置为0。出于说明目的,咱们假设此错误没有特定的异常处理程序。所以,咱们将使用general except子句,在记录错误后从新引起异常。若是您想本身尝试,只需在新的Python文件中编写前面说明的代码,而后从终端窗口运行它。如下屏幕截图显示了上述代码的输出:

try ... except


能够在try ... except子句中指定可选的else块。在其余的只发生ifno异常块被执行的尝试......除了条款。语法以下:

在其余块的前执行最后条款,咱们将在接下来的学习。

finally......clean it up!


还有其余东西能够添加到try ...除了... else story:一个可选的finally子句。顾名思义,此子句中的代码在关联的try ... except块的末尾执行。不管是否引起异常,finally子句(若是指定)将在try ... except子句的末尾执行。想象一下它是由Python提供的全天候保证!如下代码段显示了finally块的运行状况:

运行这个简单的代码将产生如下输出:

$ python finally_example1.py
Enter a number: -1
Uh oh..Assertion Error. 
Do some special cleanup

输出中的最后一行是finally子句中的print语句。

带有和不带finally子句的代码片断以下面的屏幕截图所示。即便except子句指示代码从函数返回,也确保finally子句中的代码最终执行。

在最后条款一般用于离开功能以前执行清理任务。示例用例是关闭数据库链接或文件。但请注意,为此,您还能够在Python中使用with语句。

编写一个新的异常类


建立一个从Exception派生的新异常类是微不足道的。打开Python解释器并建立如下类:

>>> class GameUnitError(Exception):
...     pass
... 
>>>

就这样!咱们有一个新的异常类GameUnitError,能够部署了。如何测试此异常?在Python解释器中键入如下代码行:

>>> raise GameUnitError("ERROR: some problem with game unit")

引起新建立的异常将打印如下回溯:

>>> raise GameUnitError("ERROR: some problem with game unit")
Traceback (most recent call last):
  File "", line 1, in 
__main__.GameUnitError: ERROR: some problem with game unit

将GameUnitError类复制到其本身的模块gameuniterror.py中,并将其保存在与attackoftheorcs_v1_1.py相同的目录中。

接下来,更新attackoftheorcs_v1_1.py文件以包含如下更改:

首先,在文件的开头添加如下import语句:

from gameuniterror import GameUnitError

第二个变化是在AbstractGameUnit.heal方法中。更新后的代码显示在如下代码段中。观察高亮代码,只要提出的价值自定义异常self.health_meter超过的self.max_hp。

经过这两个更改,运行以前建立的heal_exception_example.py。您将看到引起新的异常,如如下屏幕截图所示:

扩展异常类


咱们能够用GameUnitError类作更多的事情吗?固然!就像任何其余类同样,咱们能够定义属性并使用它们。让咱们进一步扩展这个课程。在修改后的版本中,它将接受一个额外的参数和一些预约义的错误代码。更新的GameUnitError类显示在如下屏幕截图中:

咱们来看看前面屏幕截图中的代码:

· 首先,它调用Exception超类的__init__方法,而后定义一些额外的实例变量。

· 一个新的dictionary对象self。error_dict将错误整数代码和错误信息保存为键值对。

· 该self.error_message存储有关根据提供的错误代码当前错误的信息。

· 在尝试......除了子句确保error_dict实际上已经由指定的键码的说法。它不在except子句中,咱们只是检索默认错误代码为000的值。

到目前为止,咱们已经对GameUnitError类和AbstractGameUnit.heal方法进行了更改。咱们尚未完成。拼图的最后一块是修改主要在程序heal_exception_example.py文件。代码显示在如下屏幕截图中:

咱们来看看代码:

· 因为heal_by值太大,try子句中的heal方法会引起GameUnitError异常。

· new except子句处理GameUnitError异常,就像任何其余内置异常同样。

· 在except子句中,咱们有两个print语句。第一个打印health_meter> max_hp!(回想一下,当在heal方法中引起此异常时,此字符串被做为GameUnitError实例的第一个参数给出)。第二个print语句检索并打印GameUnitError实例的error_message属性。

咱们已经作好了全部的改变。咱们能够在终端窗口中运行此示例:

$ python heal_exception_example.py

该程序的输出显示在如下屏幕截图中:

在这个简单的例子中,将错误信息打印到控制台。您能够进一步将详细错误日志写入文件,并跟踪应用程序运行时生成的全部错误消息。

相关文章
相关标签/搜索