python异常处理和断言
http://blog.csdn.net/pipisorry/article/details/21841883
关于异常处理有必要么的讨论
最重要的问题是你在开发过程中隐藏了bug,如果当时你没加这个Try…Catch,恐怕你早就发现这个bug了,因为程序压根就跑不下去。
异常处理
(含py2和py3的区别)
基本格式
Python 3
try:
...
except Exception as e:
print(e)
不过lz推荐下面的格式:
import tracebacktry:
...
except:
print(traceback.format_exc())
input("hold on...")
直接调用print Exception, e得到的结果就只有一行信息,只是异常的名字和说明而已。而这样可以输出栈信息,ide中点击就可以到达错误位置,并且不会一闪而过。
异常
1)所以异常都从 BaseException继承,并删除了StardardError 。StandardError
异常:在Python 2里,StandardError
是除了StopIteration
,GeneratorExit
,KeyboardInterrupt
,SystemExit
之外所有其他内置异常的基类。在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版本中没有实现
- 相对于Python 2里在异常类型后添加逗号,Python 3使用了一个新的关键字,
as
。 - 关键字
as
也可以用在一次捕获多种类型异常的情况下。 - 如果你捕获到一个异常,但是并不在意访问异常对象本身,Python 2和Python 3的语法是一样的。
- 类似地,如果你使用一个保险方法(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:
- 抛出不带用户自定义错误信息的异常,这种最简单的形式下,语法没有改变。
- 当你想要抛出一个带用户自定义错误信息的异常时,改变就显而易见了。Python 2用一个逗号来分隔异常类和错误信息;Python 3把错误信息作为参数传递给异常类。Python 2支持新旧两种异常触发语法,而Python 3只接受带括号的的语法(不然会触发SyntaxError)
- Python 2支持一种更加复杂的语法来抛出一个带用户自定义回溯(stack trace,堆栈追踪)的异常。在Python 3里你也可以这样做,但是语法完全不同。
- 在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 |
- 最简单的形式下,生成器抛出不带用户自定义错误信息的异常。这种情况下,从Python 2到Python 3语法上没有变化 。
- 如果生成器抛出一个带用户自定义错误信息的异常,你需要将这个错误信息字符串(error string)传递给异常类来以实例化它。
- 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] |
与异常处理相关的
[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操作的。
附录
常见的python异常类型
断言
断言是一句必须等价于布尔真的判定;此外,发生异常也意味着表达式为假.这些工作类似于 C 语言预处理器中 assert 宏,但在 Python 中它们在运行时构建(与之相对的是编译期判别).
如果你刚刚接触断言这个概念,无妨.断言可以简简单单的想象为 raise-if 语句(更准确的说是raise-if-not 语句).测试一个表达式,如果返回值是假,触发异常.
断言语句等价于这样的 Python 表达式,如果断言成功不采取任何措施(类似语句),否则触发AssertionError(断言错误)的异常.assert 的语法如下:
assert expression[, arguments]
from:http://blog.csdn.net/pipisorry/article/details/21841883
python异常处理和断言的更多相关文章
- python异常处理与断言以及日志模块
python异常处理与断言 目录: 1.异常处理 2.断言(assert) 3.日志模块(logging) 4.修改之前的车票信息查询,把日志模块.异常处理加进去 1.异常处理 代码如下: 语法: t ...
- (69)Python异常处理与断言
http://blog.csdn.net/pipisorry/article/details/21841883 断言 断言是一句必须等价于布尔真的判定;此外,发生异常也意味着表达式为假.这些工作类似于 ...
- python异常处理、断言
异常处理基本语法 捕获异常 try: 语句1 语句2 ... except ERRNAME as e: print(e) #尝试执行语句,捕获到ERRNAME异常时打印异常信息e 捕获多个异常 try ...
- 14、python异常处理及断言
前言:本文主要介绍python中异常的处理及断言,包括异常类型.异常捕获.主动跑出异常和断言. 一.异常类型介绍 什么是异常?异常即是一个事件,该事件会在程序执行过程中发生,会影响程序的正常执行,一般 ...
- [Python学习笔记][第八章Python异常处理结构与程序调试]
1/30 第八章Python异常处理结构与程序调试 异常处理 try-except结构 try: try块 except Exception: except块 try-except-else结构 tr ...
- python异常处理try,except,else,finally,raise
先看下else的使用: try: ... exception: ... else: ... 只有在try中没有发生任何异常,所有代码完全成功的情况下才会转入else 再看下finally: final ...
- Python 异常处理
Python 异常处理 python提供了两个非常重要的功能来处理python程序在运行中出现的异常和错误.你可以使用该功能来调试python程序. 异常处理: 本站Python教程会具体介绍. 断言 ...
- Python异常处理总结
一.何谓异常处理 在我们调试程序时,经常不可避免地出现意料之外的情况,导致程序不得不停止运行,然后提示大堆提示信息,大多是这种情况都是由异常引起的.异常的出现一方面是因为写代码时粗心导致的语法错误,这 ...
- Python异常处理回顾与总结
1 引言 在我们调试程序时,经常不可避免地出现意料之外的情况,导致程序不得不停止运行,然后提示大堆提示信息,大多是这种情况都是由异常引起的.异常的出现一方面是因为写代码时粗心导致的语法错误,这种错误在 ...
随机推荐
- ReactNative 4Android源码分析二: 《JNI智能指针之实现篇》
文/Tamic http://blog.csdn.net/sk719887916/article/details/53462268 回顾 上一篇介绍了<ReactNative4Android源码 ...
- Git之(六)标签管理
发布一个版本时,我们通常先在版本库中打一个标签(tag),这样,就唯一确定了打标签时刻的版本.将来无论什么时候,取某个标签的版本,就是把那个打标签的时刻的历史版本取出来.所以,标签也是版本库的一个快照 ...
- Unity UGUI图文混排(六) -- 超链接
图文混排更新到超链接这儿,好像也差不多了,不过就在最后一点,博主也表现得相当不专业,直接整合了山中双木林同学提供的超链接的解决方案,博主甚至没来得及细看就直接复制了,但感觉还是挺好用的. 博主已经将超 ...
- Github上的Android项目介绍之ListViewAnimation(针对listView item的侧滑菜单)(1)
demo源码,需要可以下载 1.这是一个github开源项目,先去github上面下载,github下载地址. 2.将SwipeMenuListView项目,导入,然后新建项目如果要引用,要设置为相应 ...
- Latex居中
居中文本 环境:\begin{center} 第一行\\第二行\\...第n行 \end{center}.可以用\\[长度]来插入可以省略的额外行间距.在一个环境内部,可以用命令\centering来 ...
- Tomcat内核之Tomcat的类加载器
跟其他主流的Java Web服务器一样,Tomcat也拥有不同的自定义类加载器,达到对各种资源库的控制.一般来说,Java Web服务器需要解决以下四个问题: ① 同一个Web服务器里,各个Web ...
- 【Unity Shaders】Vertex & Fragment Shader入门
写在前面 三个月以前,在一篇讲卡通风格的Shader的最后,我们说到在Surface Shader中实现描边效果的弊端,也就是只对表面平缓的模型有效.这是因为我们是依赖法线和视角的点乘结果来进行描边判 ...
- Objc将数据写入iOS真机的plist文件中
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 如何写入模拟器的博文在 这里 但是这对真机不管用,因为在真机环 ...
- 06_NoSQL数据库之Redis数据库:Redis的高级应用之登录授权和主从复制
Redis高级实用特征 安全性(登录授权和登录后使用auth授权) 设置客户端连接后进行任何其他指定前需要使用的密码. 警告:因为redis速度相当快,所以在一台比较好的服务器下,一个外部的用户 ...
- ubuntu14.04使用root用户登录桌面
ubuntu安装好之后,默认是不能用root用户登录桌面的,只能使用普通用户或者访客登录.怎样开启root用户登录桌面呢? 先用普通用户登录,然后切换到root用户,然后执行如下命令: vi /usr ...