Object Oriented Python 简明教程

Exception and Exception Classes

一般而言,异常是任何不寻常状况。异常通常表示错误,但有时候在程序中故意加入异常,如提早终止程序或从资源不足中回复。有许多内置的异常,表示各种状况,如读到档案结尾后,或除以零。我们可以定义我们自己的异常,称为自定义异常。

异常处理让你能优雅地处理错误,并采取有意义的作为。异常处理有两种组件:“抛出”和“捕获”。

Identifying Exception (Errors)

Python 中发生的每个错误都会产生异常,该异常将以其错误类型识别为错误状况。

>>> #Exception
>>> 1/0
Traceback (most recent call last):
   File "<pyshell#2>", line 1, in <module>
      1/0
ZeroDivisionError: division by zero
>>>
>>> var = 20
>>> print(ver)
Traceback (most recent call last):
   File "<pyshell#5>", line 1, in <module>
      print(ver)
NameError: name 'ver' is not defined
>>> #Above as we have misspelled a variable name so we get an NameError.
>>>
>>> print('hello)

SyntaxError: EOL while scanning string literal
>>> #Above we have not closed the quote in a string, so we get SyntaxError.
>>>
>>> #Below we are asking for a key, that doen't exists.
>>> mydict = {}
>>> mydict['x']
Traceback (most recent call last):
   File "<pyshell#15>", line 1, in <module>
      mydict['x']
KeyError: 'x'
>>> #Above keyError
>>>
>>> #Below asking for a index that didn't exist in a list.
>>> mylist = [1,2,3,4]
>>> mylist[5]
Traceback (most recent call last):
   File "<pyshell#20>", line 1, in <module>
      mylist[5]
IndexError: list index out of range
>>> #Above, index out of range, raised IndexError.

Catching/Trapping Exception

当你的程序中发生不寻常的事,而且你希望使用异常机制来处理它,你就要“抛出一个异常”。关键字 try 和 except 用于捕获异常。任何时候在 try 块中发生异常时,Python 会寻找匹配的 except 块来处理该异常。如果有的话,执行就会跳到那里。

syntax

try:
   #write some code
   #that might throw some exception
except <ExceptionType>:
   # Exception handler, alert the user

try 子句中的代码将逐语句执行。

如果发生异常,try 块的其余部分将被跳过,并且 except 子句将被执行。

try:
   some statement here
except:
   exception handling

让我们写一些代码,看看在你不在程序中使用任何错误处理机制时会发生什么。

number = int(input('Please enter the number between 1 & 10: '))
print('You have entered number',number)

只要使用者输入数字,以上程序就会正常运作,但如果使用者试图输入一些其他数据类型(例如字符串或列表)时,会发生什么情况?

Please enter the number between 1 > 10: 'Hi'
Traceback (most recent call last):
   File "C:/Python/Python361/exception2.py", line 1, in <module>
      number = int(input('Please enter the number between 1 & 10: '))
ValueError: invalid literal for int() with base 10: "'Hi'"

现在 ValueError 是异常类型。让我们尝试使用异常处理来重新编写上述代码。

import sys

print('Previous code with exception handling')

try:
   number = int(input('Enter number between 1 > 10: '))

except(ValueError):
   print('Error..numbers only')
   sys.exit()

print('You have entered number: ',number)

如果我们运行此程序,并且输入一个字符串(而不是数字),我们便可以看到会得到不同的结果。

Previous code with exception handling
Enter number between 1 > 10: 'Hi'
Error..numbers only

Raising Exceptions

要从你自己的方法引发错误,你需要使用 raise 关键字,如下所示

raise ExceptionClass(‘Some Text Here’)

我们举个例子

def enterAge(age):
   if age<0:
      raise ValueError('Only positive integers are allowed')
   if age % 2 ==0:
      print('Entered Age is even')
   else:
      print('Entered Age is odd')

try:
   num = int(input('Enter your age: '))
   enterAge(num)
except ValueError:
   print('Only positive integers are allowed')

运行程序并输入正整数。

Expected Output

Enter your age: 12
Entered Age is even

但是当我们尝试输入负数时,会得到,

Expected Output

Enter your age: -2
Only positive integers are allowed

Creating Custom exception class

你可以通过扩展 BaseException 类或 BaseException 的子类来创建自定义异常类。

custom exception class

从上图中,我们可以看到 Python 中大多数异常类都从 BaseException 类扩展而来。你可以从 BaseException 类或其子类派生你自己的异常类。

创建一个名为 NegativeNumberException.py 的新文件,并编写以下代码。

class NegativeNumberException(RuntimeError):
   def __init__(self, age):
      super().__init__()
      self.age = age

以上代码创建一个新异常类,名为 NegativeNumberException,它仅包含一个构造函数,该构造函数使用 super() init () 调用父类构造函数并设置年龄。

现在为了创建你自己的自定异常类,将会编写一些代码并导入新的异常类。

from NegativeNumberException import NegativeNumberException
def enterage(age):
   if age < 0:
      raise NegativeNumberException('Only positive integers are allowed')

   if age % 2 == 0:
      print('Age is Even')

   else:
      print('Age is Odd')

try:
   num = int(input('Enter your age: '))
   enterage(num)
except NegativeNumberException:
   print('Only positive integers are allowed')
except:
   print('Something is wrong')

Output

Enter your age: -2
Only positive integers are allowed

另一种创建自定异常类的方式。

class customException(Exception):
   def __init__(self, value):
      self.parameter = value

   def __str__(self):
      return repr(self.parameter)
try:
   raise customException('My Useful Error Message!')
except customException as instance:
   print('Caught: ' + instance.parameter)

Output

Caught: My Useful Error Message!

Exception hierarchy

内建异常的类层次为 −

+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
+-- StopIteration
+-- StopAsyncIteration
+-- ArithmeticError
| +-- FloatingPointError
| +-- OverflowError
| +-- ZeroDivisionError
+-- AssertionError
+-- AttributeError
+-- BufferError
+-- EOFError
+-- ImportError
+-- LookupError
| +-- IndexError
| +-- KeyError
+-- MemoryError
+-- NameError
| +-- UnboundLocalError
+-- OSError
| +-- BlockingIOError
| +-- ChildProcessError
| +-- ConnectionError
| | +-- BrokenPipeError
| | +-- ConnectionAbortedError
| | +-- ConnectionRefusedError
| | +-- ConnectionResetError
| +-- FileExistsError
| +-- FileNotFoundError
| +-- InterruptedError
| +-- IsADirectoryError
| +-- NotADirectoryError
| +-- PermissionError
| +-- ProcessLookupError
| +-- TimeoutError
+-- ReferenceError
+-- RuntimeError
| +-- NotImplementedError
| +-- RecursionError
+-- SyntaxError
| +-- IndentationError
| +-- TabError
+-- SystemError
+-- TypeError
+-- ValueError
| +-- UnicodeError
| +-- UnicodeDecodeError
| +-- UnicodeEncodeError
| +-- UnicodeTranslateError
+-- Warning
+-- DeprecationWarning
+-- PendingDeprecationWarning
+-- RuntimeWarning
+-- SyntaxWarning
+-- UserWarning
+-- FutureWarning
+-- ImportWarning
+-- UnicodeWarning
+-- BytesWarning
+-- ResourceWarning