Python 3 - 异常处理

  • 简述

    Python 提供了两个非常重要的功能来处理 Python 程序中的任何意外错误并在其中添加调试功能 -
    • Exception Handling− 这将在本教程中介绍。这是 Python 中可用的标准异常列表 -标准异常。
    • Assertions− 这将在 Python 3 断言教程中介绍。
  • 标准异常

    以下是 Python 中可用的标准异常列表。−
    序号 异常名称和描述
    1
    Exception
    所有异常的基类
    2
    StopIteration
    当迭代器的 next() 方法不指向任何对象时引发。
    3
    SystemExit
    由 sys.exit() 函数引发。
    4
    StandardError
    除 StopIteration 和 SystemExit 之外的所有内置异常的基类。
    5
    ArithmeticError
    数值计算中发生的所有错误的基类。
    6
    OverflowError
    当计算超出数字类型的最大限制时引发。
    7
    FloatingPointError
    当浮点计算失败时引发。
    8
    ZeroDivisonError
    当所有数字类型都发生除零或模零时引发。
    9
    AssertionError
    在 Assert 语句失败的情况下引发。
    10
    AttributeError
    在属性引用或分配失败的情况下引发。
    11
    EOFError
    当没有来自 raw_input() 或 input() 函数的输入并且到达文件末尾时引发。
    12
    ImportError
    当导入语句失败时引发。
    13
    KeyboardInterrupt
    当用户中断程序执行时引发,通常是按 Ctrl+c。
    14
    LookupError
    所有查找错误的基类。
    15
    IndexError
    在序列中找不到索引时引发。
    16
    KeyError
    在字典中找不到指定的键时引发。
    17
    NameError
    在本地或全局命名空间中找不到标识符时引发。
    18
    UnboundLocalError
    尝试访问函数或方法中的局部变量但未为其分配值时引发。
    19
    EnvironmentError
    在 Python 环境之外发生的所有异常的基类。
    20
    IOError
    当输入/输出操作失败时引发,例如尝试打开不存在的文件时的 print 语句或 open() 函数。
    21
    OSError
    因与操作系统相关的错误而引发。
    22
    SyntaxError
    当 Python 语法有错误时引发。
    23
    IndentationError
    未正确指定缩进时引发。
    24
    SystemError
    当解释器发现内部问题时引发,但遇到此错误时 Python 解释器不会退出。
    25
    SystemExit
    当使用 sys.exit() 函数退出 Python 解释器时引发。如果未在代码中处理,则导致解释器退出。
    26
    TypeError
    当尝试对指定数据类型无效的操作或函数时引发。
    27
    ValueError
    当数据类型的内置函数具有有效类型的参数,但参数指定了无效值时引发。
    28
    RuntimeError
    当生成的错误不属于任何类别时引发。
    29
    NotImplementedError
    当需要在继承类中实现的抽象方法实际上没有实现时引发。
  • Python 中的断言

    断言是一种健全性检查,您可以在完成程序测试后将其打开或关闭。
    • 认为断言的最简单方法是将其比作raise-if语句(或者更准确地说,是 raise-if-not 语句)。测试表达式,如果结果为假,则会引发异常。
    • 断言由 assert 语句执行,它是 Python 1.5 版中引入的最新关键字。
    • 程序员经常在函数的开头放置断言以检查有效输入,并在函数调用之后检查有效输出。

    断言声明

    当遇到 assert 语句时,Python 会评估伴随的表达式,希望它是真的。如果表达式为假,Python 会引发AssertionError异常。
    断言的语法是 -
    
    assert Expression[, Arguments]
    
    如果断言失败,Python 使用 ArgumentExpression 作为 AssertionError 的参数。可以使用 try-except 语句像任何其他异常一样捕获和处理 AssertionError 异常。如果未处理它们,它们将终止程序并产生回溯。

    例子

    这是一个将给定温度从开氏度转换为华氏度的函数。由于 0° K 已经很冷了,如果它看到负温度,该功能就会退出 -
    
    #!/usr/bin/python3
    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!
    
  • 什么是异常?

    异常是一种事件,它在程序执行期间发生,会扰乱程序指令的正常流程。通常,当 Python 脚本遇到无法应对的情况时,它会引发异常。异常是表示错误的 Python 对象。
    当 Python 脚本引发异常时,它必须要么立即处理异常,要么终止并退出。
  • 处理异常

    如果您有一些可能引发异常的可疑代码,您可以通过将可疑代码放在try:堵塞。在 try: 块之后,包含一个except:语句,然后是尽可能优雅地处理问题的代码块。

    句法

    这是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. 
    
    以下是关于上述语法的几个要点 -
    • 一个 try 语句可以有多个 except 语句。当 try 块包含可能引发不同类型异常的语句时,这很有用。
    • 您还可以提供一个通用的 except 子句,它可以处理任何异常。
    • 在 except 子句之后,您可以包含一个 else 子句。如果 try: 块中的代码没有引发异常,则执行 else 块中的代码。
    • else 块是不需要 try: 块保护的代码的好地方。

    例子

    这个例子打开一个文件,在文件中写入内容并优雅地出来,因为根本没有问题 -
    
    #!/usr/bin/python3
    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()
    
    这会产生以下结果 -
    
    Written content in the file successfully
    

    例子

    这个例子试图打开一个你没有写权限的文件,所以它引发了一个异常 -
    
    #!/usr/bin/python3
    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
    
  • 没有异常的异常条款

    您还可以使用 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 语句不被认为是一种好的编程习惯,因为它捕获所有异常但不会让程序员识别可能发生的问题的根本原因。
  • 具有多个异常的 except 子句

    您还可以使用相同的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. 
    
  • try-finally 条款

    你可以使用finally:连同一个块try:堵塞。这finally:块是放置任何必须执行的代码的地方,无论 try 块是否引发异常。try-finally 语句的语法是这样的 -
    
    try:
       You do your operations here;
       ......................
       Due to any exception, this may be skipped.
    finally:
       This would always be executed.
       ......................
    
    Note− 您可以提供 except 子句或 finally 子句,但不能同时提供两者。您不能将else子句与 finally 子句一起使用。

    例子

    
    #!/usr/bin/python3
    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")
       fh.close()
    
    如果您没有以写入模式打开文件的权限,那么这将产生以下结果 -
    
    Error: can't find file or read data
    
    同样的例子可以写得更干净如下 -
    
    #!/usr/bin/python3
    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")
    
    这会产生以下结果 -
    
    Going to close the file
    
    当try块中抛出异常时,执行将立即传递到finally块。执行完finally块中的所有语句后,再次引发异常,如果存在于try-except语句的下一个更高层,则在except语句中处理。
  • 异常参数

    异常可以有一个argument,它是一个提供有关问题的附加信息的值。参数的内容因异常而异。您可以通过在 except 子句中提供一个变量来捕获异常的参数,如下所示 -
    
    try:
       You do your operations here
       ......................
    except ExceptionType as Argument:
       You can print value of Argument here...
    
    如果您编写代码来处理单个异常,则可以在 except 语句中的异常名称后面加上一个变量。如果要捕获多个异常,则可以在异常的元组后面添加一个变量。
    该变量接收主要包含异常原因的异常值。变量可以以元组的形式接收单个值或多个值。该元组通常包含错误字符串、错误编号和错误位置。

    例子

    以下是单个异常的示例 -
    
    #!/usr/bin/python3
    # 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'
    
  • 引发异常

    您可以使用 raise 语句以多种方式引发异常。的一般语法raise声明如下 -

    句法

    
    raise [Exception [, args [, traceback]]]
    
    这里,Exception是异常的类型(例如,NameError),argument是异常参数的值。参数是可选的;如果未提供,则异常参数为 None。
    最后一个参数 traceback 也是可选的(在实践中很少使用),如果存在,则是用于异常的 traceback 对象。

    例子

    异常可以是字符串、类或对象。Python 核心引发的大多数异常都是类,其参数是该类的一个实例。定义新的异常非常容易,可以按如下方式完成 -
    
    def functionName( level ):
       if level <1:
          raise Exception(level)
          # The code below to this would not be executed
          # if we raise the exception
       return level
    
    Note− 为了捕获异常,“except”子句必须引用作为类对象或简单字符串抛出的相同异常。例如,要捕获上述异常,我们必须编写如下的 except 子句 -
    
    try:
       Business Logic here...
    except Exception as e:
       Exception handling here using e.args...
    else:
       Rest of the code here...
    
    以下示例说明了引发异常的用法 -
    
    #!/usr/bin/python3
    def functionName( level ):
       if level <1:
          raise Exception(level)
          # The code below to this would not be executed
          # if we raise the exception
       return level
    try:
       l = functionName(-10)
       print ("level = ",l)
    except Exception as e:
       print ("error in level argument",e.args[0])
    
    这将产生以下结果
    
    error in level argument -10
    
  • 用户定义的异常

    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