错误和异常
有(至少)两种可区分的错误:语法错误和异常。
while True print('Hello world')
File "<stdin>", line 1
while True print('Hello world')
^
SyntaxError: invalid syntax
即使语句或表达式在语法上是正确的,在尝试执行时也可能会导致错误。在执行过程中检测到的错误称为异常,并不是无条件致命的:您将很快了解如何在Python程序中处理它们。然而,大多数异常都不是由程序处理的,并导致错误消息如下所示:
>>> 10 * (1/0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero
>>> 4 + spam*3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'spam' is not defined
>>> '2' + 2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't convert 'int' object to str implicitly
上面的例子我们得到了ZeroDivisionError, NameError and TypeError这几种异常,实际上在python里面官方给定的异常有很多。
处理异常
先看一下一般的结构
while True:
try:
x = int(input("Please enter a number: "))
break
except ValueError:
print("Oops! That was no valid number. Try again...")
我们现在来了解一个关键字raise(抛出异常):
你可以在任意地方 raise **Error抛出异常。
我们总结一下except的几种用法:
- except **Error: 期望捕获一个类型错误
- except (**Error, **Error): 可以捕获多个类型错误
- except Exception: 捕获任意类型错误
- except **Error as err: 获取error的一个实例
当然我们需要注意的是捕获异常是一个自底向上的过程,实际上raise 后面可以跟上任意一个类,我们待会儿会来了解异常处理的运行机制。
完整的异常处理:
try:
except:
finally: (无论报错还是不报都要进行的代码片段,用于clean up actions)
自定义异常
程序可以通过创建一个新的异常类来命名自己的异常(有关Python类的更多信息,请参阅类)。异常通常应该直接或间接地从异常类派生。
可以定义异常类,它们可以做任何其他类可以做的事情,但通常保持简单,通常只提供一些属性,允许异常处理程序提取关于错误的信息。当创建一个可以引起几个不同错误的模块时,通常的做法是为该模块定义的异常创建一个基类,以及为不同错误条件创建特定异常类的子类:
class Error(Exception):
"""Base class for exceptions in this module."""
pass
class InputError(Error):
"""Exception raised for errors in the input.
Attributes:
expression -- input expression in which the error occurred
message -- explanation of the error
"""
def __init__(self, expression, message):
self.expression = expression
self.message = message
class TransitionError(Error):
"""Raised when an operation attempts a state transition that's not
allowed.
Attributes:
previous -- state at beginning of transition
next -- attempted new state
message -- explanation of why the specific transition is not allowed
"""
def __init__(self, previous, next, message):
self.previous = previous
self.next = next
self.message = message
异常处理的底层原理
1.基于线程。
2.操作系统层面的调用。
3.当一个线程出现错误时,操作系统给你一个机会被告知这个错误。
简单的来说就是出现异常后,堆栈就会清空当前并且恢复出问题之前的内容。