Python 简明教程

Python - Exceptions Handling

Exception Handling in Python

Python 中的异常处理是指在程序执行期间可能发生的运行时错误的管理。在 Python 中,当程序执行期间出现错误或意外情况(例如除以零、尝试访问不存在的文件或尝试针对不兼容的数据类型执行操作)时,将会引发异常。

Python 提供了两个非常重要的功能来处理 Python 程序中的任何意外错误,并添加调试功能−

  1. Exception Handling −这将在本教程中进行介绍。以下是 Python 中可用的标准异常列表: Standard Exceptions

  2. Assertions −这将在 Assertions in Python 教程中进行介绍。

Assertions in Python

断言是一种健全检查,当您完成对程序的测试后,您可以将其开启或关闭。

最简单的考虑断言的方法是将其比作 raise-if 语句(或更准确地说,比作 raise-if-not 语句)。对某个表达式进行测试,如果结果为假,则引发一个异常。

程序员经常在函数开始时放置断言来检查有效输入,并在函数调用后检查有效输出。

The assert Statement

当遇到 assert 语句时,Python 会计算随附的表达式,希望它为真。如果表达式为假,Python 会引发 AssertionError 异常。

assert 的 syntax 是 −

assert Expression[, Arguments]

如果断言失败,Python 会使用 ArgumentExpression 作为 AssertionError 的参数。可以使用 try-except 语句捕获和处理 AssertionError 异常,就像处理任何其他异常一样,但如果没有处理,它们将终止程序并生成回溯。

这是一个将开尔文温度转换为华氏温度的函数。由于绝对零度有多冷,因此如果函数看到负温度,则会中止 −

def KelvinToFahrenheit(Temperature):
   assert (Temperature >= 0),"Colder than absolute zero!"
   return ((Temperature-273)*1.8)+32
print (KelvinToFahrenheit(273))
print (int(KelvinToFahrenheit(505.78)))
print (KelvinToFahrenheit(-5))

执行上述代码后,将生成以下结果 −

32.0
451
Traceback (most recent call last):
File "test.py", line 9, in <module>
print (KelvinToFahrenheit(-5))
File "test.py", line 4, in KelvinToFahrenheit
assert (Temperature >= 0),"Colder than absolute zero!"
AssertionError: Colder than absolute zero!

What is Exception?

异常是一种事件,它在程序执行期间发生,会中断程序指令的正常流。通常情况下,当 Python 脚本遇到无法处理的情况时,它会引发异常。异常是表示错误的 Python 对象。

当 Python 脚本引发异常时,它必须立即处理该异常,否则它将终止并退出。

Handling an Exception in Python

如果您有一些可能引发异常的可疑代码,您可以通过将可疑代码放置在 try :块中来防御您的程序。在 try :块后面,包含一个 except :语句,后面是一个以尽可能优雅的方式处理问题的代码块。

  1. try :块包含可能导致异常的语句

  2. 如果发生异常,程序将跳到 except :块。

  3. 如果 try :块中没有异常,则 except :块将被跳过。

Syntax

以下是 try…​except…​else 块的简单语法 −

try:
   You do your operations here
   ......................
except ExceptionI:
   If there is ExceptionI, then execute this block.
except ExceptionII:
   If there is ExceptionII, then execute this block.
   ......................
else:
   If there is no exception then execute this block.

以下关于上述语法是几个重要要点 −

  1. 单个 try 语句可以有许多 except 语句。当 try 块包含可能引发不同类型异常的语句时,这很有用。

  2. 您还可以提供一个通用的 except 子句,它可以处理任何异常。

  3. 在 except 子句之后,您可以包含一个 else 子句。如果 try: 块中的代码不引发异常,则 else 块中的代码将执行。

  4. else 代码块适用于无需 try: 代码块保护的代码。

Example

此示例将打开一个文件,在该文件中写内容,并优雅地退出,因为根本不存在任何问题。

try:
   fh = open("testfile", "w")
   fh.write("This is my test file for exception handling!!")
except IOError:
   print ("Error: can\'t find file or read data")
else:
   print ("Written content in the file successfully")
   fh.close()

它将生成以下 output

Written content in the file successfully

但是,将 open() 函数中的模式参数更改为“w”。如果 testfile 尚不存在,则程序在 except 代码块中会遇到 IOError,并打印以下错误消息:

Error: can't find file or read data

Example

此示例尝试打开一个文件,而你没有写入权限,因此会引发异常:

try:
   fh = open("testfile", "r")
   fh.write("This is my test file for exception handling!!")
except IOError:
   print ("Error: can\'t find file or read data")
else:
   print ("Written content in the file successfully")

这会产生以下结果:

Error: can't find file or read data

The except Clause with No Exceptions

你还可以使用如下所示,不定义任何异常的 except 语句:

try:
   You do your operations here;
   ......................
except:
   If there is any exception, then execute this block.
   ......................
else:
   If there is no exception then execute this block.

此类 try-except 语句会捕捉到发生的全部异常。然而,使用这种 try-except 语句不被视为良好的编程实践,因为它会捕捉到全部异常,但是并不会让程序员识别到可能发生的根本问题。

The except Clause with Multiple Exceptions

你还可以使用相同的 except 语句来处理多个异常,如下所示:

try:
   You do your operations here;
   ......................
except(Exception1[, Exception2[,...ExceptionN]]]):
   If there is any exception from the given exception list,
   then execute this block.
   ......................
else:
   If there is no exception then execute this block.

The try-finally Clause

你可以使用 finally: 代码块和 try: 代码块。finally 代码块是一个存放必须执行的任何代码的地方,无论 try-block 是否引发了异常。try-finally 语句的语法如下:

try:
   You do your operations here;
   ......................
   Due to any exception, this may be skipped.
finally:
   This would always be executed.
   ......................

你无法同时使用 else 子句及 finally 子句。

Example

try:
   fh = open("testfile", "w")
   fh.write("This is my test file for exception handling!!")
finally:
   print ("Error: can\'t find file or read data")

如果无权以写入模式打开文件,那么这将产生以下结果:

Error: can't find file or read data

可以按如下方式更简洁地编写相同的示例:

try:
   fh = open("testfile", "w")
   try:
      fh.write("This is my test file for exception handling!!")
   finally:
      print ("Going to close the file")
      fh.close()
except IOError:
   print ("Error: can\'t find file or read data")

如果在 try 代码块中引发了异常,则执行将立即传递到 finally 代码块。在 finally 代码块中的全部语句执行完毕之后,异常会再次引发,并且在 try-except 语句的下一层中存在时,将在 except 语句中处理异常。

Argument of an Exception

异常可以具有一个参数,它是一个关于问题提供附加信息的值。参数的内容根据异常而有所不同。你通过如下在 except 子句中提供一个变量来捕获异常的参数:

try:
   You do your operations here;
   ......................
except ExceptionType, Argument:
   You can print value of Argument here...

如果编写代码来处理单个异常,则可以在 except 语句中让一个变量跟在异常名称后面。如果正在捕捉多个异常,则可以让一个变量跟在异常元组的后面。

此变量接收异常的值,该值大多包含异常的成因。此变量可以接收单个值,或以元组形式接收多个值。此元组通常包含错误字符串、错误号和错误位置。

Example

下面是一个处理单个异常的示例:

# Define a function here.
def temp_convert(var):
   try:
      return int(var)
   except ValueError as Argument:
      print ("The argument does not contain numbers\n", Argument)

# Call above function here.
temp_convert("xyz")

这会产生以下结果:

The argument does not contain numbers
invalid literal for int() with base 10: 'xyz'

Raising an Exceptions

你可以使用 raise 语句,通过几种方法引发异常。 raise 语句的通用语法如下。

Syntax

raise [Exception [, args [, traceback]]]

在此处,Exception 是异常类型(例如,NameError),而 argument 是异常参数值。argument 是可选的;如果不提供,则异常参数为 None。

最后一个参数跟踪也是可选的(实际上很少会使用),如果存在,则它将成为异常所使用的追踪对象。

Example

异常可以是字符串、类或对象。Python 核心触发的异常大部分都是类,而参数则是类的实例。定义新异常非常简单,可以像下面这样操作:

def functionName( level ):
   if level < 1:
      raise "Invalid level!", level
      # The code below to this would not be executed
      # if we raise the exception

Note: 为了捕获异常,“except”子句必须引用相同异常所引发的类对象或简单字符串。例如,为了捕获上述异常,我们必须将 except 子句写成如下内容:

try:
   Business Logic here...
except "Invalid level!":
   Exception handling here...
else:
   Rest of the code here...

User-Defined Exceptions

Python 还允许你通过从标准内置异常派生类来创建自己的异常。

下面是一个与 RuntimeError 有关的示例。此处,创建了一个从 RuntimeError 继承的类。当异常被捕获时,这是在需要显示更多特定信息时有用的。

在 try 块中,自定义异常被触发并在 except 块中被捕获。变量 e 用于创建 Networkerror 类的实例。

class Networkerror(RuntimeError):
   def __init__(self, arg):
      self.args = arg

因此,一旦定义了上述类,你就可以如下触发异常:

try:
   raise Networkerror("Bad hostname")
except Networkerror,e:
   print (e.args)

Standard Exceptions

下面是 Python 中提供的标准异常列表:

Sr.No.

Exception Name & Description

1

Exception 所有异常的基类

2

StopIteration 当迭代器的 next() 方法无法指向任何对象时引发。

3

SystemExit 由 sys.exit() 函数引发。

4

StandardError 除 StopIteration 和 SystemExit 之外所有内置异常的基类。

5

ArithmeticError 针对数字计算中发生的所有错误的基类。

6

OverflowError 当计算超出数字类型的最大限制时引发。

7

FloatingPointError 当浮点计算失败时引发。

8

ZeroDivisionError 当针对所有数字类型执行除法或求模运算时引发。

9

AssertionError 在 Assert 语句失败时引发。

10

AttributeError 在属性引用或赋值失败时引发。

11

EOFError 当 raw_input() 或 input() 函数没有输入且达到文件尾部时引发。

12

ImportError 当 import 语句失败时引发。

13

KeyboardInterrupt 在用户中断程序执行时引发,通常情况下是按下 Ctrl+c。

14

LookupError 所有查找错误的基本基类。

15

IndexError 在序列中找不到索引时引发。

16

KeyError 在字典中找不到指定的键时引发。

17

NameError 在本地或全局命名空间中找不到标识符时引发。

18

UnboundLocalError 尝试在函数或方法中访问局部变量,但未向其分配任何值时引发。

19

EnvironmentError 所有发生在 Python 环境外部的异常的基本基类。

20

IOError 输入/输出操作失败时引发,比如在试图打开一个不存在的文件时,print 语句或 open() 函数。

21

IOError 针对与操作系统相关的错误引发。

22

SyntaxError 当 Python 语法出现错误时引发。

23

IndentationError 当缩进未正确指定时引发。

24

SystemError 当解释器碰到内部错误时引发,但是当出现此错误时,Python 解释器不会退出。

25

SystemExit 当使用 sys.exit() 函数退出 Python 解释器时引发。如果在代码中未处理,则导致解释器退出。

26

TypeError 当针对指定的数据类型尝试了无效的操作或函数时引发。

27

ValueError 当数据类型的内置函数具有有效类型的参数,但是指定的参数具有无效值时引发。

28

RuntimeError 当生成的错误未归入任何类别时引发。

29

NotImplementedError 当需要在继承类中实现的抽象方法实际上未实现时引发。