Python编程语言已经被广泛应用于数据分析、深度学习以及网站搭建,虽然其相对来说较为易用,但在编程过程中难免会遇到各种异常或报错。本文将总结平时遇到的异常状况,并分别教大家如何一步步解决。
语法错误
我们将讨论的第一种错误是简单的语法错误。语法错误也称为“解析错误”。一般情况下,解析错误会阻止程序执行。例如:
在Python2中上面的代码可以顺利执行,但在Python3中会出现如下错误:
在这种情况下,没有执行任何代码。 Python 3无法将parse_errors.py识别为有效的Python代码,因此它不会执行任何操作。
让我们看另一个例子:
注意明显缺了一个 “:”,这将导致Python2和3中的语法错误:
另一个有趣的行为是当我们导入模块时发生语法错误:
在Python2中的运行结果:
这完全符合预期,因为语法在Python 2中都是有效的。但是在Python 3中运行它有点不同:
这次错误消息有点冗长。它有一个特殊的名字:Traceback。在我们深入研究Tracebacks之前,了解一下名为“Call Stack”的内容非常重要。
异常和Traceback
我们先看下面的代码(无错误):
一旦定义了各种函数,标记的行将func3推送到调用堆栈,func3然后推送func2,func2推送func1。现在func1从调用堆栈弹出,因为它返回1到func2,然后弹出func2,因为它返回1到func3。
如果所有推送和弹出听起来让你感到困惑,请看一下Python调用堆栈的(Call Stack)相关解释。
现在让我们介绍一个错误:
如果您运行此代码,将引发异常:
这是如何运作的?它就像上面介绍的那样,func3,func2和func1被推送到调用堆栈。然后在func1中有一个运行时错误,因为它试图除以零。这引发了异常:Exception是一种特殊的Python对象,用于存储有关错误的信息。 Traceback是一条描述调用堆栈的消息,每个堆栈帧都会简要描述。
在某种程度上,异常可以被认为是一种特殊的返回。来看下面的代码:
调用func_a会得到一个正常的字符串,但调用func_b将引发异常并停止执行。并且这些print语句都不会被执行。
修复错误
读懂Traceback是相当简单的(即使错误本身并不总是很容易修复)。这是我们上面获得的Traceback:
Traceback的最后一部分描述了引发的实际异常。稍微向上移动,您会看到我们的脚本第2行的func1引发了异常。向上移动一些,你可以看到func2在脚本的第5行调用了func1,依此类推。
上面给出的例子非常简单。有时Traceback还不足以自行显示错误。在这种情况下,您有一些可以提供帮助的不同工具。
print:您可以打印出变量值等,以深入了解发生的情况。这通常称为“打印调试”。它快速而暴力,通常效果不错。如果您执行了打印调试,请在完成后删除打印语句
logging.debug:Python有一个特殊的日志记录模块,它比打印调试更加智能,并通常被认为比打印调试更好。如果你不知道如何使用日志模块,那么不要太担心,它不是严格必要的。但它相当不错,你可以自行在网上了解它。
Python还有一个内置调试器,您可以使用它逐行遍历代码。它允许您在程序运行时探索和交互程序,这非常有用。
还有一些Python库可以使Tracebacks提供更多异常信息。例如TBVaccine。
当然,预防错误的方法也有很多:
代码测试。我建议使用pytest,也可以偶尔使用doctest。
类型提示。在代码中使用类型提示可以完全消除整个错误类别。
把异常作为对象
Python中的所有东西都是一个对象,这也包括异常。当引发异常时,这意味着创建了Exception类的实例。由于Exception类实际上是一个类,因此它也可以有子类。
在这里,我们看到KeyError是Exception的子类:
请注意,我们不需要导入任何包执行上述代码的操作,一般情况下代码中发生的异常总是在内置的基本异常范围内。如果您要创建自己的Exception类,则需要在引用它们的任何地方导入它们(就像常规类一样)。
我们可以用IndexError做同样的事情:
到这里,我们简单介绍了一些异常,和部分异常处理的方法,后面我们会进行更复杂的异常及其处理方法的介绍。
感谢有你,不见不散!
END
本公众号原创作品,未经授权禁止转载,特此声明,谢谢合作!
领取专属 10元无门槛券
私享最新 技术干货