初识Python(8)__Python错误和异常

错误和异常

##################################################################################

参考:http://blog.csdn.net/fcoolx/article/details/4202872

http://blog.163.com/[email protected]/blog/static/279729562008719384580/

https://docs.python.org/2/library/exceptions.html#bltin-exceptions

http://www.pythondoc.com/pythontutorial27/errors.html#tut-raising

##################################################################################

What

什么是错误和异常?

错误是指在执行代码过程中发生的事件,它中断或干扰代码的正常流程并创建异常对象。当错误中断流程时,该程序将尝试寻找异常处理程序(一段告诉程序如何对错误做出响应的代码),以帮助程序恢复流程。换句话说,错误是一个事件,而异常是该事件创建的对象。

当使用短语“产生异常”时,表示存在问题的方法发生错误,并创建异常对象(包含该错误的信息及发生的时间和位置)来响应该错误。导致出现错误和随后异常的因素包括用户错误、资源失败和编程逻辑失败。这些错误与代码实现特定任务的方法有关,而与该任务的目的无关。

why

异常怎么发生的?

异常的抛出机制:

1、如果在运行时发生异常,解释器会查找相应的处理语句(称为handler).

2、要是在当前函数里没有找到的话,它会将异常传递给上层的调用函数,看看那里能不能处理。

3、如果在最外层(全局“main”)还是没有找到的话,解释器就会退出,同时打印出traceback以便让用户找到错误产生的原因。

注意:虽然大多数错误会导致异常,但一个异常不一定代表错误,有时候它们只是一个警告,有时候它们可能是一个终止信号,比如退出循环等。

为什么要处理异常?

如果不进行异常处理,即不对错误做出响应,程序的健壮性就会大打折扣,甚至无法保证正常运行,所以必须要进行异常处理。

异常类型有哪些?

异常类型参考:https://docs.python.org/2/library/exceptions.html#bltin-exceptions

基础异常类型

BaseException               #所有异常的基类

 +-- SystemExit             #python 解释器请求退出

 +-- KeyboardInterrupt      #用户中断执行(通常是输入^C)

 +-- GeneratorExit          #生成器(generator)发生异常来通知退出

 +-- Exception              #常规错误的基类

      +-- StopIteration     #迭代器没有更多的值

      +-- StandardError     #所有的内建标准异常的基类

      |    +-- BufferError

      |    +-- ArithmeticError           #所有数值计算错误的基类

      |    |    +-- FloatingPointError   #浮点计算错误

      |    |    +-- OverflowError        #数值运算超出最大限制

      |    |    +-- ZeroDivisionError    #除(或取模)零 (所有数据类型)

      |    +-- AssertionError    #断言语句失败

      |    +-- AttributeError    #对象没有这个属性

      |    +-- EnvironmentError  #操作系统错误的基类

      |    |    +-- IOError      #输入输出错误

      |    |    +-- OSError      #操作系统错误

      |    |         +-- WindowsError (Windows)   #Windows 系统调用失败    

      |    |         +-- VMSError (VMS)

      |    +-- EOFError                #没有内建输入,到达EOF 标记

      |    +-- ImportError             #导入模块/对象失败

      |    +-- LookupError             #无效数据查询的基类

      |    |    +-- IndexError         #序列中没有没有此索引(index)

      |    |    +-- KeyError           #映射中没有这个键

      |    +-- MemoryError             #内存溢出错误(对于Python 解释器不是致命的)

      |    +-- NameError               #未声明/初始化对象 (没有属性)

      |    |    +-- UnboundLocalError  #访问未初始化的本地变量

      |    +-- ReferenceError          #弱引用(Weak reference)试图访问已经垃圾回收了的对象

      |    +-- RuntimeError            #一般的运行时错误

      |    |    +-- NotImplementedError#尚未实现的方法

      |    +-- SyntaxError             #Python 语法错误

      |    |    +-- IndentationError   #缩进错误

      |    |         +-- TabError      #Tab 和空格混用

      |    +-- SystemError             #一般的解释器系统错误

      |    +-- TypeError               #对类型无效的操作

      |    +-- ValueError              #传入无效的参数

      |         +-- UnicodeError       #Unicode 相关的错误

      |              +-- UnicodeDecodeError    #Unicode 解码时的错误

      |              +-- UnicodeEncodeError    #Unicode 编码时错误

      |              +-- UnicodeTranslateError #Unicode 转换时错误

      +-- Warning    #警告的基类

           +-- DeprecationWarning          #关于被弃用的特征的警告

           +-- PendingDeprecationWarning   #关于特性将会被废弃的警告

           +-- RuntimeWarning              #可疑的运行时行为(runtime behavior)的警告

           +-- SyntaxWarning               #可疑的语法的警告

           +-- UserWarning                 #用户代码生成的警告

           +-- FutureWarning               #关于构造将来语义会有改变的警告

           +-- ImportWarning

           +-- UnicodeWarning

           +-- BytesWarning
1、NameError:尝试访问一个未申明的变量

>>>  v
NameError: name ‘v‘ is not defined

2、ZeroDivisionError:除数为0
>>> v = 1/0
ZeroDivisionError: int division or modulo by zero

3、SyntaxError:语法错误
>>> int int
SyntaxError: invalid syntax (<pyshell#14>, line 1)

4、IndexError:索引超出范围
>>> List = [2]
>>> List[3]
Traceback (most recent call last):
  File "<pyshell#18>", line 1, in <module>
    List[3]
IndexError: list index out of range

5、KeyError:字典关键字不存在
>>> Dic = {‘1‘:‘yes‘, ‘2‘:‘no‘}
>>> Dic[‘3‘]
Traceback (most recent call last):
  File "<pyshell#20>", line 1, in <module>
    Dic[‘3‘]
KeyError: ‘3‘

6、IOError:输入输出错误
>>> f = open(‘abc‘)
IOError: [Errno 2] No such file or directory: ‘abc‘

7、AttributeError:访问未知对象属性
>>> class Worker:
 def Work():
  print("I am working")
>>> w = Worker()
>>> w.a
Traceback (most recent call last):
  File "<pyshell#51>", line 1, in <module>
    w.a
AttributeError: ‘Worker‘ object has no attribute ‘a‘

8、ValueError:数值错误
>>> int(‘d‘)
Traceback (most recent call last):
  File "<pyshell#54>", line 1, in <module>
    int(‘d‘)
ValueError: invalid literal for int() with base 10: ‘d‘

9、TypeError:类型错误
>>> iStr = ‘22‘
>>> iVal = 22
>>> obj = iStr + iVal;
Traceback (most recent call last):
  File "<pyshell#68>", line 1, in <module>
    obj = iStr + iVal;
TypeError: Can‘t convert ‘int‘ object to str implicitly

10、AssertionError:断言错误
>>> assert 1 != 1
Traceback (most recent call last):
  File "<pyshell#70>", line 1, in <module>
    assert 1 != 1
AssertionError

如何处理异常?

使用try—except 等语句来处理选定异常,例如

>>> while True:
...     try:
...         x = int(raw_input("Please enter a number: "))
...         break
...     except ValueError:
...         print "Oops!  That was no valid number.  Try again..."
...

try语句按如下方式工作

l  首先,try从句(在关键字try和except之间的语句)被执行。

l  如果没有异常发生,except从句被跳过,try语句执行完毕。

l  如果在执行try语句的时候有异常发生,剩余的语句会被跳过。如果它的类型和except后面的命名异常相匹配,这个except从句被执行,然后在try语句后面继续执行

l  如果有异常发生,并且它和except从句中的命名异常类型不匹配,它被传递到外层的try语句,如果没有发现处理程序,它就是一个未处理的异常,程序停止执行,显示上面的错误信息。

一个try语句或许有多个except从句,来为不同的异常指定处理程序。至多一个处理程序将被执行。处理程序只处理发生在相应try从句中的异常,而不处理发生在同一个try语句的其它处理程序中的异常。一个except从句可以命名多个异常,使用一个括号元组,例如:

... except (RuntimeError, TypeError, NameError):
...     pass

最后一个except从句或许可以忽略异常的名字,作为通配符。这样使用应该极其谨慎,因为这样容易掩饰掉一个真正的编程错误。它也可以被用来打印一个错误信息,然后重新引发这个异常(也允许调用者来处理这个异常):

import sys
try:
    f = open(‘myfile.txt‘)
    s = f.readline()
    i = int(s.strip())

except IOError as e:
    print "I/O error({0}): {1}".format(e.errno, e.strerror)

except ValueError:
    print "Could not convert data to an integer."

except:
    print "Unexpected error:", sys.exc_info()[0]

    raise

try...except语句有一个可选的else从句,如果有的话必须跟在所有的except从句后面。对于那些异常没有发生时必须执行的代码非常有用。例如:

for arg in sys.argv[1:]:
    try:
        f = open(arg, ‘r‘)
    except IOError:
        print ‘cannot open‘, arg
    else:
        print arg, ‘has‘, len(f.readlines()), ‘lines‘
        f.close()

使用 else 子句比在 try 子句中附加代码要好,因为这样可以避免 try ... except 意外的截获本来不属于它们保护的那些代码抛出的异常。

Finally 子句,无论异常是否发生,是否捕捉都会执行的一段代码。

下面是try-except-else-finally 语法的示例:

try:
A
except MyException: B
else: C
finally: D   #无论如何都执行

>>> def divide(x, y):
...     try:
...         result = x / y
...     except ZeroDivisionError:
...         print "division by zero!"
...     else:
...         print "result is", result
...     finally:
...         print "executing finally clause"
...

>>> divide(2, 1)
result is 2
executing finally clause

>>> divide(2, 0)
division by zero!
executing finally clause

>>> divide("2", "1")
executing finally clause

Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 3, in divide

TypeError: unsupported operand type(s) for /: ‘str‘ and ‘str‘

finally 子句在任何情况下都会执行。 TypeError 在两个字符串相除的时候抛出,未被 except 子句捕获,因此在 finally 子句执行完毕后重新抛出。

try-except 和try-finally 包含的方式

ccfile = None

try:
    try:
        ccfile = open(‘carddata.txt‘, ‘r‘)
        txns = ccfile.readlines()

finally:
    if ccfile:
    ccfile.close()

except IOError:
    log.write(‘no txns this month\n‘)

一个这样写的理由是如果在finally 的语句块内发生了一个异常,你可以创建一个同现有的异常处理器在同一个(外)层次的异常处理器来处理它.这样,从本质上来说,就可以同时处理在原始的try语句块和finally 语句块中发生的错误.这种方法唯一的问题是,当finally 语句块中的确发生异常时,你会丢失原来异常的上下文信息,除非你在某个地方保存了它.

反对这种写法的一个理由是:在很多情况下,异常处理器需要做一些扫尾工作,而如果你在异常处理之前,用finally 语句块中释放了某些资源,你就不能再去做这项工作了.简单的说,finally 语句块并不是如你所想的是"最终的(final)"了.

一个最终的注意点:如果finally 中的代码引发了另一个异常或由于return,break,continue 语法而终止,原来的异常将丢失而且无法重新引发.

若要捕获所有异常,则可以:

try:
    :
except Exception, e:
# error occurred, log ‘e‘, etc

因为Exception是在异常继承树结构的最顶层,异常的捕获都是向下包容的,比如except LookupError,这样LookupError下的IndexError和KeyErroe异常就都能被捕获

异常参数

当异常被引发后参数是作为附加帮助信息传递给异常处理器的,异常原因是可选。

# single exception
except Exception[, reason]:
suite_for_Exception_with_Argument

# multiple exceptions
except (Exception1, Exception2, ..., ExceptionN)[, reason]:
suite_for_Exception1_to_ExceptionN_with_Argument

reason 将会是一个包含来自导致异常的代码的诊断信息的类实例. 异常参数自身会组成一个元组,并存储为类实例(异常类的实例)的属性. 上边的第一种用法中, reason 将会是一个Exception 类的实例.

>>> while True:
         try:
                   x = int(raw_input(‘please enter a number:‘))
                   break
         except ValueError, e(or, except ValueError as e):
                   print ‘ValueError‘

please enter a number:a
ValueError
please enter a number:5
>>> type(e)
<type ‘exceptions.ValueError‘>
>>> print e
invalid literal for int() with base 10: ‘a‘
>>> 

我们首先在一个try 语句块中引发一个异常,随后简单的忽略了这个异常,但保留了错误的信息。调用内置的type()函数,我们可以确认我们的异常对象的确是ValueError 异常类的实例。最后我们对异常诊断参数调用print 以显示错误。

综合了这一章目前我们所见过的所有不同的可以处理异常的语法样式:

try:

    try_suite

    except Exception1:
        suite_for_Exception1

    except (Exception2, Exception3, Exception4):
        suite_for_Exceptions_2_3_and_4

    except Exception5, Argument5:
        suite_for_Exception5_plus_argument

    except (Exception6, Exception7), Argument67:
        suite_for_Exceptions6_and_7_plus_argument

except:
    suite_for_all_other_exceptions

else:
    no_exceptions_detected_suite

finally:
    always_execute_suite

触发异常

--raise语句

rasie 一般的用法是:

raise [SomeException [, args [, traceback]]]

第一个参数,SomeExcpetion,是触发异常的名字.如果有,它必须是一个字符串,类或实例

第二个符号为可选的args(比如参数,值),来传给异常.

第三个参数traceback,同样是可选的(实际上很少用它),

raise 语句允许程序员强制抛出一个指定的异常。例如:

>>> raise NameError(‘HiThere‘)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
NameError: HiThere

如果你需要明确一个异常是否抛出,但不想处理它, raise 语句可以让你很简单的重新抛出该异常:

>>> try:
...     raise NameError(‘HiThere‘)
... except NameError:
...     print ‘An exception flew by!‘
...     raise
...

An exception flew by!

Traceback (most recent call last):
  File "<stdin>", line 2, in ?
NameError: HiThere

用户自定义异常

在程序中可以通过创建新的异常类型来命名自己的异常(Python 类的内容请参见 类 )。异常类通常应该直接或间接的从 Exception 类派生,例如:

>>> class MyError(Exception):
...     def __init__(self, value):
...         self.value = value
...     def __str__(self):
...         return repr(self.value)
...

>>> try:
...     raise MyError(2*2)
... except MyError as e:
...     print ‘My exception occurred, value:‘, e.value
...

My exception occurred, value: 4

>>> raise MyError(‘oops!‘)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
__main__.MyError: ‘oops!
时间: 2024-10-11 03:54:16

初识Python(8)__Python错误和异常的相关文章

Python学习_07_错误、异常

地毯式地过语法终于快要结束了... Python中的常见异常 1.NameError:尝试访问一个未初始化的变量 2. ZeroDivisionError:除数为0 3. SyntaxError:Python解释器语法错误 4. IndexError:请求的索引超出序列的范围 5. KeyError:请求一个不存在的字典关键字 6. IOError:输入.输出错误 7. AttributeError:尝试访问未知的对象属性 等,这些错误都是来自于Exception类,Exception类和Sys

初识Python(5)__Python映射和集合

映射类型:字典 字典:可以快速查到某个特定的词语(键),从而找到它的定义(值).(没有顺序)键和值之间用冒号(:)隔开,项之间用逗号(,)隔开,字典由{}括起来 >>> dict1 = {} #空字典 >>> dict2 = {'name': 'earth', 'port': 80} #用{}创建 >>> dict1, dict2 ({}, {'port': 80, 'name': 'earth'}) >>> fdict = dict

初识Python(9)__Python函数

函数 参考 : ######################################################### http://www.w3cschool.cc/python/python-functions.html http://developer.51cto.com/art/200809/88052.htm http://www.pythondoc.com/pythontutorial27/controlflow.html#tut-functions http://see

初识Python(1)__Python基础

Python基础 一.  注释(#) Python注释语句是用“#”字符开始,注释可以在一行的任何地方开始,解释器会忽略掉该行 # 之后的所有内容. 单行注释:   1 print ‘hello, world!’ #打印 hello,world 多行注释:多行注释用三引号’’’将需要注释的部分括起来,例如: 1 ’’’ 2 Hello ,world. 3 I’m Jay, and l like python. 4 ’’’ 3. 中文注释:需要在文件头写上: #coding=gbk 或者 #cod

初识Python(4)__Python序列

序列 序列包含:字符串,列表和元组 序列基本操作符 索引:seq[ind] 获得下标为ind 的元素 分片( [], [:], [::] ):seq[ind1:ind2] 获得下标从ind1 到ind2 间的元素集合 重复操作符( * ):seq * expr 序列重复expr 次 连接操作符( + ):sequence1 + sequence2,该表达式的结果是一个包含sequence1 和sequence2 的内容的新序列 判断成员资格:obj in/not in seq 判断obj 元素是

初识Python(2)__Python 对象

Python 对象 python中一切皆为对象,所谓对象:我自己就是一个对象,我玩的电脑就是对象,坐着的椅子就是对象,家里养的小狗也是一个对象...... 我们通过描述属性(特征)和行为来描述一个对象的.比如家里的小狗,它的颜色,大小,年龄,体重等是它的属性或特征.它会汪汪叫,会摇尾巴等是它的行为. 我们在描述一个真实对象(物体)时包括两个方面: 它可以做什么(行为) 它是什么样的(属性或特征). 在python中,一个对象的特征也称为属性(attribute).它所具有的行为也称为方法(met

初识Python(3)__Python 数字

数字类型 关于删除数字对象 按照Python 的法则, 你无法真正删除一个数值对象, 你仅仅是不再使用它而已.如果你实际上想删除一个数值对象的引用, 使用 del 语句 Python支持四种数字类型 整型:通常被称为只是整数或整数,是正或负整数,不带小数点. 长整型:非常长的整型,在数字最后有L,如“51924361L” 浮点数:双精度浮点数,浮点数值通常都有一个小数点和一个可选的后缀e(大写或小写,表示科学计数法).在e和指数之间可以用正(+)或负(-)表示指数的正负(正数的话可以省略符号)

初识Python(10)__Python模块

模块 什么是模块 自我包含并且有组织的代码片断就是模块( module ) 模块是Pyhon最高级别的程序组织单元,它将程序代码和数据封装起来以便重用.实际的角度,模块往往对应Python程序文件.每个文件都是一个模块,并且模块导入其他模块之后就可以使用导入模块定义的变量名.模块可以由两个语句和一个重要的内置函数进行处理.import: 使客户端(导入者)以一个整体获取一个模块.from:容许客户端从一个模块文件中获取特定的变量名.reload:在不中止Python程序的情况下,提供了一个重新载

10 错误和异常 - 《Python 核心编程》

?? 什么是异常? ?? Python 中的异常 ?? 探测和处理异常 ?? 上下文管理 ?? 引发异常 ?? 断言 ?? 标准异常 ?? 创建异常 ?? 相关模块 10.1 什么是异常人们需要一个"柔和"的处理错误的方法, 而不是终止程序. 错误 从软件方面来说, 错误是语法或是逻辑上的. 当 Python 检测到一个错误时, 解释器就会指出当前流已经无法继续执行下去. 这时候就出现了异常. 语法错误 语法错误指示软件的结构上有错误, 导致不能被解释器解释或编译器无法编译. 逻辑错误