使用Python进行异常处理

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

本文阅读时长:10min

本文所涉及知识点

  • Python中有哪些异常 ?

  • 使用try ... except子句控制程序流

  • 通过处理异常来处理常见问题

  • 创建和使用自定义异常类

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

什么是异常?


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

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

最常见的异常


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

image

以下是一些异常情况:

image

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

异常处理

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

image

我们来看看前面的代码片段:

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

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

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

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

image

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

image

该试块调用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关键字重新引发异常而不使用任何参数。

这是一个示例,显示如何重新引发异常:

image

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

image

try ... except


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

image

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

finally......clean it up!


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

image

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

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

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

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

image

在最后条款通常用于离开功能之前执行清理任务。示例用例是关闭数据库连接或文件。但请注意,为此,您还可以在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。

image

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

image

扩展异常类


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

image

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

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

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

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

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

image

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

image

我们来看看代码:

· 由于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

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

image

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,125评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,293评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,054评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,077评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,096评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,062评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,988评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,817评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,266评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,486评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,646评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,375评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,974评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,621评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,642评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,538评论 2 352

推荐阅读更多精彩内容