异常处理在任何一门编程语言里都是值得关注的一个话题,良好的异常处理可以让你的程序更加健壮,清晰的错误信息更能帮助你快速修复问题。在Python中,和不部分高级语言一样,使用了try/except/finally语句块来处理异常,如果你有其他编程语言的经验,实践起来并不难。
Python中的异常是什么?
Python有许多内置的异常 ,当其中的某些错误出现时,它们会强制您的程序输出错误。
当发生这些异常时,它将导致当前进程停止并将其传递给调用进程,直到被处理为止。如果不处理,我们的程序将崩溃。
例如,如果函数A调用函数B,后者又调用函数C,并且在函数C中发生异常。如果不在C中处理该异常,则该异常将传递给B,然后传递给A。
如果不进行处理,就会抛出一条错误消息,我们的程序就会意外地突然停止。
在Python中捕捉异常
在Python中,可以使用try语句处理异常。
可能引发异常的关键操作放在try子句中,并且将处理异常的代码编写在except子句中。
捕获异常后,我们将执行什么操作取决于我们自己。这是一个简单的示例。
示例
# 导入模块sys以获取异常的类型
import sys
randomList = ['a', 0, 2]
for entry in randomList:
try:
print("The entry is", entry)
r = 1/int(entry)
break
except:
print("Oops!",sys.exc_info()[0],"occured.")
print("Next entry.")
print()
print("The reciprocal of",entry,"is",r)
输出结果
The entry is a
Oops! <class 'ValueError'> occured.
Next entry.
The entry is 0
Oops! <class 'ZeroDivisionError' > occured.
Next entry.
The entry is 2
The reciprocal of 2 is 0.5
在此程序中,我们循环执行,直到用户输入具有有效倒数的整数。可能导致异常的部分放在try块中。
如果没有异常发生,则跳过除块以外的内容,并继续正常流程。但是,如果发生任何异常,它将被except块捕获。
在这里,我们使用sys模块中的exinfo()函数打印异常的名称,并要求用户再试一次。我们可以看到值‘a’和‘1.3’会导致ValueError,‘0’会导致ZeroDivisionError。
捕获Python中的特定异常
在上面的示例中,我们没有在except子句中提到任何异常。
这不是一个好的编程习惯,因为它将捕获所有异常并以相同的方式处理每种情况。 我们可以指定except子句会捕获哪些异常。
一个try子句可以有任意数量的except子句来以不同的方式处理它们,但是在发生异常时只会执行一个except子句。
我们可以使用值的元组在except子句中指定多个异常。下面是一个伪代码示例。
try:
#执行某些代码
pass
except ValueError:
# 处理ValueError异常
pass
except (TypeError, ZeroDivisionError):
# 处理多个异常
# TypeError 和 ZeroDivisionError 异常
pass
except:
# 处理所有其他异常
pass
引发异常
在Python编程中,异常是在运行时出现相应错误时抛出的,但是我们可以使用关键字raise强制抛出异常。
我们还可以选择将值传递给异常,以阐明为什么会引发异常。
>>> raise KeyboardInterrupt
Traceback (most recent call last):
...
KeyboardInterrupt
>>> raise MemoryError("This is an argument")
Traceback (most recent call last):
...
MemoryError: This is an argument
>>> try:
... a = int(input("输入一个正整数: "))
... if a <= 0:
... raise ValueError("这不是一个正数!")
... except ValueError as ve:
... print(ve)
...
输入一个正整数: -2
这不是一个正数!
try...finally
Python中的try语句可以有一个可选的finally子句。不管在什么情况下都会执行这个子句,它通常用于释放外部资源。
例如,我们可以通过网络连接到远程数据中心,或者使用文件或使用图形用户界面(GUI)。
在所有这些情况下,无论资源是否成功,我们都必须清除该资源。这些操作(关闭文件,GUI或与网络断开连接)在finally子句中执行,以确保执行。
这是一个文件操作的示例来说明这一点。
try:
f = open("test.txt",encoding = 'utf-8')
# 执行文件操作
finally:
f.close()
这种类型的构造确保即使发生异常也关闭文件。