(69)Python异常处理与断言

http://blog.csdn.net/pipisorry/article/details/21841883

断言

断言是一句必须等价于布尔真的判定;此外,发生异常也意味着表达式为假.这些工作类似于 C 语言预处理器中 assert 宏,但在 Python 中它们在运行时构建(与之相对的是编译期判别).
如果你刚刚接触断言这个概念,无妨.断言可以简简单单的想象为 raise-if 语句(更准确的说是raise-if-not 语句).测试一个表达式,如果返回值是假,触发异常.

断言语句等价于这样的 Python 表达式,如果断言成功不采取任何措施(类似语句),否则触发AssertionError(断言错误)的异常.assert 的语法如下:
assert expression[, arguments]

示例assert mode in ["train", "eval", "inference"],如果输入的mode不在其中则触发异常

[Python中何时使用断言]

关于异常处理有必要么的讨论

最重要的问题是你在开发过程中隐藏了bug,如果当时你没加这个Try…Catch,恐怕你早就发现这个bug了,因为程序压根就跑不下去。

[try catch 对代码运行的性能影响]

[你写的Try...Catch真的有必要么?]

异常处理

(含py2和py3的区别)

基本格式

Python 3
try:

...

except Exception as e:
    print(e)

不过lz推荐下面的格式:

import traceback
try:        ...        except:                print(traceback.format_exc())        input("hold on...")

直接调用print Exception, e得到的结果就只有一行信息,只是异常的名字和说明而已。而这样可以输出栈信息,ide中点击就可以到达错误位置,并且不会一闪而过。

异常

1)所以异常都从 BaseException继承,并删除了StardardError 。StandardError异常:在Python 2里,StandardError是除了StopIterationGeneratorExitKeyboardInterruptSystemExit之外所有其他内置异常的基类。在Python 3里,StandardError已经被取消了;使用Exception替代。

Notes Python 2 Python 3
  x =StandardError() x =Exception()
  x =StandardError(a, b, c) x =Exception(a, b, c)

2)去除了异常类的序列行为和.message属性

3)异常链,因为__context__在3.0a1版本中没有实现

  1. 相对于Python 2里在异常类型后添加逗号,Python 3使用了一个新的关键字,as
  2. 关键字as也可以用在一次捕获多种类型异常的情况下。
  3. 如果你捕获到一个异常,但是并不在意访问异常对象本身,Python 2和Python 3的语法是一样的。
  4. 类似地,如果你使用一个保险方法(fallback)来捕获所有异常,Python 2和Python 3的语法是一样的。

在导入模块(或者其他大多数情况)的时候,你绝对不应该使用这种方法(指以上的fallback)。不然的话,程序可能会捕获到像KeyboardInterrupt(如果用户按Ctrl-C来中断程序)这样的异常,从而使调试变得更加困难。

触发异常-raise语句

Python 3里,抛出自定义异常的语法有细微的变化。

Notes Python 2 Python 3
raise MyException unchanged
raise MyException,‘error message‘ raise MyException(‘error message‘)
raise MyException,‘error message‘, a_traceback raise MyException(‘error message‘).with_traceback(a_traceback)
raise ‘error message‘ unsupported

Note:

  1. 抛出不带用户自定义错误信息的异常,这种最简单的形式下,语法没有改变。
  2. 当你想要抛出一个带用户自定义错误信息的异常时,改变就显而易见了。Python 2用一个逗号来分隔异常类和错误信息;Python 3把错误信息作为参数传递给异常类。Python 2支持新旧两种异常触发语法,而Python 3只接受带括号的的语法(不然会触发SyntaxError)
  3. Python 2支持一种更加复杂的语法来抛出一个带用户自定义回溯(stack trace,堆栈追踪)的异常。在Python 3里你也可以这样做,但是语法完全不同。
  4. 在Python 2里,你可以抛出一个不带异常类的异常,仅仅只有一个异常信息。在Python 3里,这种形式不再被支持。2to3将会警告你它不能自动修复这种语法。

使用lambda匿名函数抛出异常

How can I write a lambda expression that‘s equivalent to:
def x():
    raise Exception()
The following is not allowed:
y = lambda : raise Exception()

lambda errmsg: exec(‘raise(Exception(errmsg))‘)

[Define a lambda expression that raises an Exception]

生成器的throw方法

在Python 2里,生成器有一个throw()方法。调用a_generator.throw()会在生成器被暂停的时候抛出一个异常,然后返回由生成器函数获取的下一个值。在Python 3里,这种功能仍然可用,但是语法上有一点不同。

Notes Python 2 Python 3
a_generator.throw(MyException) no change
a_generator.throw(MyException,‘error message‘) a_generator.throw(MyException(‘error message‘))
a_generator.throw(‘error message‘) unsupported
  1. 最简单的形式下,生成器抛出不带用户自定义错误信息的异常。这种情况下,从Python 2到Python 3语法上没有变化 。
  2. 如果生成器抛出一个带用户自定义错误信息的异常,你需要将这个错误信息字符串(error string)传递给异常类来以实例化它。
  3. Python 2还支持抛出只有异常信息的异常。Python 3不支持这种语法,并且2to3会显示一个警告信息,告诉你需要手动地来修复这处代码。

异常处理

Python 3中的异常处理也发生了一点变化。在Python 3中必须使用“as”关键字。

Python 2

try:
    let_us_cause_a_NameError
except NameError, err:
    print err, ‘--> our error message‘

name ‘let_us_cause_a_NameError‘ is not defined --> our error message

Python 3
try:
    let_us_cause_a_NameError
except NameError as err:
    print(err, ‘--> our error message‘)

name ‘let_us_cause_a_NameError‘ is not defined --> our error message

except的一个例子:

考虑下面这个文件

import sys

def bar(i):
    if i == 1:
        raise KeyError(1)

def bad():
    e = None
    try:
        bar(int(sys.argv[1]))
    except KeyError as e:
        print(‘key error‘)
    print(e)

bad()

在python2中一切运作正常

$ python foo.py 1
key error
1

但是在python3中事情变得一团糟

$ python3 foo.py 1

key error
Traceback (most recent call last):
  File "foo.py", line 19, in <module>
    bad()
  File "foo.py", line 17, in bad
    print(e)
UnboundLocalError: local variable ‘e‘ referenced before assignment

Note:问题出在,在Python3中,异常对象无法在异常块作用域外访问。(原因是在垃圾收集器运行且从内存中清理引用之前会在内存栈帧中保存一个引用周期)

解决此问题的方法之一是在异常块作用域外围护一个异常对象的引用,以使其可访问。这里是前例使用这一技术的一个版本,使得代码对Python2和Python3都友好:

import sys
def bar(i):
    if i == 1:
        raise KeyError(1)

def good():
    exception = None
    try:
        bar(int(sys.argv[1]))
    except KeyError as e:
        exception = e
        print(‘key error‘)
    print(exception)

除0异常ZeroDivisionError

现在除以变量A=0都不会被try-except捕捉到了,会直接在运行时警告:

RuntimeWarning: divide by zero encountered in double_scalars

只有直接除以0才会被try-except捕捉到

其它异常

x,y为字典,如果x < y的不能比较,抛出TypeError异常。2.x版本是返回伪随机布尔值的。

sys.exc_type, sys.exc_value, sys.exc_traceback

处理异常的时候,在sys模块里有三个你可以访问的变量:sys.exc_type,sys.exc_value,sys.exc_traceback。(实际上这些在Python 1的时代就有。)从Python 1.5开始,由于新出的sys.exc_info,不再推荐使用这三个变量了,这是一个包含所有以上三个元素的元组。在Python 3里,这三个变量终于不再存在了;这意味着,你必须使用sys.exc_info。

Notes Python 2 Python 3
  sys.exc_type sys.exc_info()[0]
  sys.exc_value sys.exc_info()[1]
  sys.exc_traceback sys.exc_info()[2]

皮皮blog

与异常处理相关的

[python上下文管理器ContextLib及with语句]

else配合 try except错误控制使用

在异常处理语句中,当try代码块没有抛出任何的异常时,else语句块会被执行到。
def my_to_int(str_param):
    try:
        print int(str_param)
    except ValueError:
        print ‘cannot convert {} to a integer‘.format(str_param)
    else:
        print ‘convert {} to integer successfully‘.format(str_param)
my_to_int("123")
my_to_int("me123")
convert 123 to integer successfully
cannot convert me123 to a integer

如打印日志所示,在转换成功未发生错的的时候,else语句里的逻辑会被执行,当然这个例子可能并没有什么太多的实际的用处,但大致能说明else在错误处理中的用处:简化逻辑,避免使用一些标志值就能够准确把握是否发生错误的情况来做一些实际的操作(比如在保存数据的时候如果发生错误,在else语句块中进行rollback的操作,然后紧接着还能加上finally语句完成一些清理操作。

Great Exceptations

Exceptions作为一种控制结构,在处理数据库、sockets、文件或者任何可能失败的资源时非常常用。使用标准的 try 、except 结构写数据库操作时通常是类型这样的方式。
try:
    # get API data
    data = db.find(id=‘foo‘) # may raise exception
    # manipulate the data
    db.add(data)
    # save it again
    db.commit() # may raise exception
except Exception:
    # log the failure
    db.rollback()
 
db.close()
你能发现这里的问题吗?这里有两种可能的异常会触发相同的except模块。这意味着查找数据失败(或者为查询数据建立连接失败)会引发回退操作。这绝对不是我们想要的,因为在这个时间点上事务并没有开始。同样回退也不应该是数据库连接失败的正确响应,因此让我们将不同的情况分开处理。

首先,我们将处理查询数据。
try:
    # get API data
    data = db.find(id=‘foo‘) # may raise exception
except Exception:
    # log the failure and bail out
    log.warn("Could not retrieve FOO")
    return

# manipulate the data
db.add(data)
现在数据检索拥有自己的try-except,这样当我们没有取得数据时,我们可以采取任何处理方式。没有数据我们的代码不大可能再做有用的事,因此我们将仅仅退出函数。除了退出你也可以构造一个默认对象,重新进行检索或者结束整个程序。
现在让我们将commit的代码也单独包起来,这样它也能更优雅的进行错误处理。
try:
    db.commit() # may raise exception
except Exception:
    log.warn("Failure committing transaction, rolling back")
    db.rollback()
else:
    log.info("Saved the new FOO")
finally:
    db.close()
实际上,我们已经增加了两端代码。首先,让我们看看else,当没有异常发生时会执行这里的代码。在我们的例子中,这里只是将事务成功的信息写入日志,但是你可以按照需要进行更多有趣的操作。一种可能的应用是启动后台任务或者通知。
很明显finally 子句在这里的作用是保证db.close() 总是能够运行。回顾一下,我们可以看到所有和数据存储相关的代码最终都在相同的缩进级别中形成了漂亮的逻辑分组。以后需要进行代码维护时,将很直观的看出这几行代码都是用于完成 commit操作的。

皮皮blog

附录

常见的python异常类型

[Python异常编程技巧]

from:http://blog.csdn.net/pipisorry/article/details/21841883

时间: 2024-10-31 15:46:35

(69)Python异常处理与断言的相关文章

14、python异常处理及断言

前言:本文主要介绍python中异常的处理及断言,包括异常类型.异常捕获.主动跑出异常和断言. 一.异常类型介绍 什么是异常?异常即是一个事件,该事件会在程序执行过程中发生,会影响程序的正常执行,一般情况下,在python无法正常处理程序时就会发生一个异常. 异常是python对象,表示一个错误.当python脚本发生异常时我们需要捕获处理它,否则程序会终止执行. 在python 中,所有的异常都是派生自BaseException类的实例,下面介绍几种常见几种异常: BaseException:

Python 异常处理

Python 异常处理 python提供了两个非常重要的功能来处理python程序在运行中出现的异常和错误.你可以使用该功能来调试python程序. 异常处理: 本站Python教程会具体介绍. 断言(Assertions):本站Python教程会具体介绍. python标准异常 异常名称 描述 BaseException 所有异常的基类 SystemExit 解释器请求退出 KeyboardInterrupt 用户中断执行(通常是输入^C) Exception 常规错误的基类 StopIter

Python异常处理总结

一.何谓异常处理 在我们调试程序时,经常不可避免地出现意料之外的情况,导致程序不得不停止运行,然后提示大堆提示信息,大多是这种情况都是由异常引起的.异常的出现一方面是因为写代码时粗心导致的语法错误,这种错误在程序编译时就可以发现:另一方面也可能是因为程序逻辑错误,这种错误往往是不可避免地,只能通过异常处理来防止程序退出. 二.异常类型 Python自带的异常处理机制非常强大,提供了很多内置异常类,可向用户准确反馈出错信息.Python是面向对象语言,认为一切皆对象,所以异常也是对象.Python

Python异常处理与程序调试

Python异常处理与程序调试 Python提供了强大的异常处理机制,通过捕获异常可以提高程序的健壮性.异常处理还具有释放对象,中止循环的运行等作用.在程序运行的过程中,如果发生了错误,可以返回事先约定的一个错误代码. "try...except"语句 用于处理问题语句,捕获可能存在的异常.try子句的代码块中放置的可能出现异常的语句,except子句中的代码用于处理异常.当异常出现时,Python会自动生成一个异常对象. >>> try: ... f = open(

Python 异常处理--raise函数用法

raise语句手工引发一个异常: 1 "raise" [expression ["," expression ["," expression]]] 在Python中,要想引发异常,最简单的形式就是输入关键字raise,后跟要引发的异常的名称.异常名称标识出具体的类: Python异常处理是那些类的对象.执行raise语句时,Python会创建指定的异常类的一个对象.raise语句还可指定对异常对象进行初始化的参数.为此,请在异常类的名称后添加一个

十一、Python异常处理

Python异常处理 异常抛出机制,为程序开发人员提供了一种在运行时发现错误,进行回复处理,然后继续执行的能力 #!/usr/bin/python try: open('abc.txt') except IOError,msg: pass 抛出机制: 如果在运行时发生异常的话,解释器会查找相应的处理语句(称为handler) 要是在当前函数力没有找到的话,它会将异常传递给上层的调用函数,看看那里能不能处理 如果在最外层(全局"main")还是没有找到的话,解释器就会退出,同时打印出tr

第十节:python异常处理、类

python个人笔记,纯属方便查询. -----------------------python异常处理------------------------- try:         name=['a','b','c']         name[3] except IndexError:         print 'you list is out of range.........' 意思是让原本的错误改成自己想要的错误提示. try:         name=['a','b','c']  

python异常处理和面向对象编程总结

异常处理和面向对象编程,是python编程中,比较重要的基础.在实际生产编程设计和开发中,异常处理和面向读象都是必须在设计和开发过程中充分考虑的.    对于python开发和面向对象这两部分基础,用一个python程序进行封装说明,结果如下: #!/usr/bin/env python # _*_ coding:utf-8 _*_ ################# #异常处理 ################# print ''' 异常处理是用于处理软件或信息系统中出现的异常状况的一种机制,

python之异常处理,断言和反射

1.异常基础 python在运行过程中,程序解释机制会测试代码,如检测不通过则会抛出异常. try: aa = 10 bb = '10' cc = aa + bb except Exception as e: print('error:',e) #output输出异常,数字不能与字符向加 error: unsupported operand type(s) for +: 'int' and 'str' try: aa = 10 bb = '10' cc = aa + bbexcept TypeE