Python学习9——异常

Python使用异常对象来表示异常状态,并在遇到错误时引发异常。

 

raise语句可以引发异常,将一个类或实例作为参数。

>>> raise Exception     #引发的是通用异常,没有指出是什么错误
Traceback (most recent call last):
  File "<pyshell#120>", line 1, in <module>
    raise Exception
Exception
>>> 
>>> raise Exception('hyperdrive overload')   #添加了错误消息yperdrive overload
Traceback (most recent call last):
  File "<pyshell#125>", line 1, in <module>
    raise Exception('hyperdrive overload')
Exception: hyperdrive overload

 

一些内置的异常类

类名 描述
Exception 几乎所有的异常类都是从它派生而来的
AttributeError 引用属性或给它赋值失败时引发
OSError 操作系统不能执行指定的任务(如打开文件)时引发,有多个子类
IndexError 使用序列中不存在的索引时引发,为LookupError的子类
KeyError 使用映射中不存在的键时引发,为LookupError的子类
NameError 找不到名称(变量)时引发
SyntaxError 代码不正确时引发
TypeError 将内置操作或函数用于类型不正确的对象时引发
ValueError 将内置操作或函数用于这样的对象时引发:其类型正确但包含的值不合适
ZeroDivisionError 在除法或求模运算的第二个参数为零时引发

 

捕获异常后,如果重新引发它(继续向上传播),可调用raise且不提供任何参数。

>>> class MuffledCalculator:
    muffled = False     #关闭“抑制”功能,引发异常
    def calc(self,expr):
        try:
            return eval(expr)
        except ZeroDivisionError:
            if self.muffled:
                print('Division by zero is illegal')
            else:
                raise

            
>>> calculator = MuffledCalculator()
>>> calculator.calc('10/2')
5.0
>>> calculator.calc('10/0')       #捕获异常ZeroDivisionError后,继续向上传播它
Traceback (most recent call last):
  File "<pyshell#17>", line 1, in <module>
    calculator.calc('10/0')
  File "<pyshell#14>", line 5, in calc
    return eval(expr)
  File "<string>", line 1, in <module>
ZeroDivisionError: division by zero      
>>> calculator.muffled = True   #打开“抑制”功能,打印一条错误信息,不让异常继续传播
>>> calculator.calc('10/0')
Division by zero is illegal

eval函数:将字符串str当成有效的表达式来求值并返回计算结果。

 

可使用raise...from...语句来提供自己的异常上下文,也可使用None来禁用上下文。

>>> try:
    1/0
except ZeroDivisionError:
    raise ValueError from None

Traceback (most recent call last):
  File "<pyshell#28>", line 4, in <module>
    raise ValueError from None
ValueError

 

一个except子句捕获多种异常,可在一个元组中指定这些异常:

>>> try:
    x= int(input('enter 1:'))
    y= int(input('enter 2:'))
    print(x/y)
except(ZeroDivisionError,TypeError,NameError):
    print('.......')

    
enter 1:1
enter 2:0
.......

 

合理使用else子句:

>>> while True:
    try:
        x = int(input('enter your first number:'))
        y = int(input('enter your second number:'))
        value = x/y
        print('x / y is ',value)
    except:
        print('Invalid input.Plase try again')
    else:
        break

    
enter your first number:10
enter your second number:0
Invalid input.Plase try again
enter your first number:2
enter your second number:m
Invalid input.Plase try again
enter your first number:5
enter your second number:'9'
Invalid input.Plase try again
enter your first number:10
enter your second number:2
x / y is  5.0

当没有引发异常时,才会跳出循环。如果出现错误,程序会要求用户提供新的输入。

 

>>> while True:
    try:
        x = int(input('enter your first name:'))
        y = int(input('enter your second name:'))
        value = x/y
        print('x/y is ',value)
    except Exception as e:
        print('Invalid input:',e)
        print('Plase try agagin')
    else:
        break

    
enter your first name:10
enter your second name:0
Invalid input: division by zero
Plase try agagin
enter your first name:10
enter your second name:p
Invalid input: invalid literal for int() with base 10: 'p'
Plase try agagin
enter your first name:'10'
Invalid input: invalid literal for int() with base 10: "'10'"
Plase try agagin
enter your first name:10
enter your second name:2
x/y is  5.0

使用except Exception as e可以在程序中打印更有用的错误消息。

 

finally子句,可用于在发生异常时执行清理工作。与try子句配套使用.

>>> try:
    1/0
except NameError:
    print('Unknown variable')
else:
    print('That went well!')
finally:
    print('Cleaning up.')

    
Cleaning up.
Traceback (most recent call last):
  File "<pyshell#89>", line 2, in <module>
    1/0
ZeroDivisionError: division by zero

 

 

栗子:假设有一个字典,你要在指定的键存在时打印与之相关联的值,否则什么都不做。

>>> def describe_person(person):
    print('Description of',person['name'])
    print('age:',person['age'])
    if 'occupation' in person:
        print('Occupation:',person['occupation'])

        
>>> p = dict(name='Throatwobbler Mangrove',age=25)
>>> describe_person(p)
Description of Throatwobbler Mangrove
age: 25

这段代码很直观,但它必须两次查找'occupation'键:1次检查这个键是否存在(条件中),另一次获取这个键的值,打印。

优化一下:

>>> def describe_person(person):
    print('Description of',person['name'])
    print('age:',person['age'])
    try:
        print('Occupation:',person['occupation'])   #函数直接假设存在'occupation',如果假设成立,直接获取并打印值,不用检查键是否存在。
    except KeyError:pass

    
>>> p = dict(name='Throatwobbler Mangrove',age=25)
>>> describe_person(p)
Description of Throatwobbler Mangrove
age: 25

 

>>> while True:

         try:

                   x = int(input('enter your first name:'))

                   y = int(input('enter your second name:'))

                   value = x/y

                   print('x/y is ',value)

         except Exception as e:

                   print('Invalid input:',e)

                   print('Plase try agagin')

         else:

                   break

 

        

enter your first name:10

enter your second name:0

Invalid input: division by zero

Plase try agagin

enter your first name:10

enter your second name:p

Invalid input: invalid literal for int() with base 10: 'p'

Plase try agagin

enter your first name:'10'

Invalid input: invalid literal for int() with base 10: "'10'"

Plase try agagin

enter your first name:10

enter your second name:2

x/y is  5.0

 

posted @ 2019-06-30 23:27  酸菜泡饭  阅读(206)  评论(0编辑  收藏  举报