Throwing and Catching Exceptions

    异常就是一个Python对象,它表示一个 error。

 

1、推卸责任:传播异常

    当一个函数产生了一个异常,它要么是立刻处理该异常,要么是终止运行。如果这个函数没有处理那个异常,则它的 caller 可能会处理此异常。如果 caller 不处理,则它也会立刻终止运行。异常会顺着调用栈一直往上传播,直到某人处理了它。如果就是没有,则整个程序就终止了。

    通常,返回一个值的函数应当返回 None 来指示一个“reasonable” failure,对于“unreasonable” problems 才生成一个异常。

 

2、处理异常

    如果你有一些“受怀疑”的代码(可能会出现异常),此时可以将这些代码放到一个 try: block 中来保护它们。在 try: block 后面,包含一个 except 语句,紧跟着就是用于处理问题的代码。

Listing 5-5: NumberGuess2.py

import random

import sys

# This line chooses a random integer >=1 and <=100.

# (See Chapter 15 for a proper explanation.)

SecretNumber=random.randint(1,100)

print “I’m thinking of a number between 1 and 100.”

# Loop forever (at least until the user hits Ctrl-Break).

while (1): 

    print “Guess my number.”

    # The following line reads a line of input from 

    # the command line and converts it to an integer.

    try:

        NumberGuess=int(sys.stdin.readline())

    except ValueError:

        print “Please type a whole number.”

        continue 

    if (NumberGuess==SecretNumber):

        print “Correct!  Choosing a new number...”

        SecretNumber=random.randint(1,100)

    elif (NumberGuess > SecretNumber):

        print “Lower.”

    else:

        print “Higher.”

3、More on exceptions

    一个异常可以有一个 argument, 它提供关于问题的额外信息。argument 的内容(以及甚至它的类型)会随着异常而变化。你捕获一个异常的 argument,是通过在 except语句中提供一个变量:

except ExceptionType, ArgumentVariable。

    可以提供多个 except 语句来处理各种类型的异常。这种情况下,异常会被首个合适的 except 语句来处理。你还可以提供一个通用的 except 语句,它处理任何异常。如果你这么做了,我高度

建议你在处理异常。因为默默地吞没异常可能会掩盖重要的 bugs,like a NameError。这里是一些 cookie-cutter 代码,我把它用于 quick-and-dirty 错误处理:

try:

    DoDangerousStuff()

except:

# The show must go on!

# Print the exception and the stack trace, and continue.

    (ErrorType,ErrorValue,ErrorTB)=sys.exc_info()

    print sys.exc_info()

    traceback.print_exc(ErrorTB)

    在 except 语句后面,可以放一个 else 语句,try: block 中的代码如果没有出现异常就会执行 else 块中的代码。else 块中非常适合写那种不需要 try: block 保护的代码。

    如果你尝试打开一个不存在的文件,Python 会产生一个异常。

try:

    OptionsFile = open("SecretOptions.txt")

except IOError, (ErrorNumber, ErrorString):

    # Assume our default option values are all OK.

    # We need a statement here, but we have nothing

    # to do, so we pass.

    pass 

else:

    # This executes if we opened it without an IOError.

    ParseOptionsFile(OptionsFile)

4、Defining and raising exceptions

    你可以利用 raise exceptionType, argument 语句来生成异常。Argument 就是 exception argument 的一个值。Argument 是可选的;不过不提供,exception argument 就是 None。

    一个异常可以是一个 string、 一个类、或者一个对象。Python core 生成的大多数异常都是 classes,并带一个是该 class的一个实例的 argument。

    定义新异常相当简单,下面就是一个:

def CalculateElfHitPoints(Level):

    if Level < 1:

        raise “Invalid elf level!”,Level

    # (The code below won’t execute if we raise

    # the exception.)

    HitPoints = 0

    for DieRoll in range(Level):

        HitPoints += random.randint(1,6)

    为了捕捉一个异常,except 语句必须指向相同的抛出的异常。Python 通过 reference identity 来比较 string exceptions。因此,如果代码生成“BigProblem”,and a except-clause for "BigProblem,",except语句就不会捕捉该异常。(这些 string 是相等的,但可能没指向内存中的相同点)。要正确地处理异常,应该用一个命名常量字符串,或一个 class。

5、Cleaning up with finally

    还有一个处理失败的机制就是 finally 块。你可以提供 except 语句,或一个 finally 语句,不必都提供。

    例如,多线程程序常常用锁来阻止线程踩踏各自的数据。如果一个线程得到了一个锁并崩溃了但没有释放这个锁,那么其他线程将永远等待——这就叫死锁。finally 语句就很适合这样的工作:

try:

    DataLock.acquire()

    # ... do things with the data ...

finally:

    # This code *must* execute. The fate of the

    # free world hangs in the balance!

    DataLock.release() 

猜你喜欢

转载自zsjg13.iteye.com/blog/2230358