#计算机# #程序员# #python# #代码# #IT#
网站建设哪家好,找创新互联公司!专注于网页设计、网站建设、微信开发、小程序制作、集团企业网站建设等服务项目。为回馈新老客户创新互联还提供了瑞丽免费建站欢迎大家使用!
程序在运行的时候,如果python解释器遇到 不是语法错误 时,会停止程序的执行,并且抛出一些错误的信息进行提示,这就是异常。
方式try-except语句捕获 所有发生的异常 。但这不是一个很好的方式,我们不能通过该程序识别出具体的异常信息。因为它捕获所有的异常,常用于函数最外层进行捕捉未知异常。
1)情况1
2)情况2
3)情况3
当在try块中抛出一个异常,立即执行finally块代码。
finally块中的所有语句执行后,异常被再次触发,并执行except块代码。
在不确定异常是哪个的情况下,常用的except的异常有: Exception、BaseException 。
关注我,坚持每日积累一个技巧, 长期坚持 ,我们将会不断进步。
在python中会遇到两种错误,一种,是==语法错误==,这种错误不能被解释器容忍,必须更改为正确语法后程序才能运行;而另外一种,是在==程序运行过程中出现的错误==,诸如==NameError==,==TypeError==等此类错误,有错误名称和行号以及报错内容的错误,称之为==异常==。
名词解释:
[]:方括号内的内容不必一定出现
try:异常捕获块,有且仅有一个
except:异常处理块,可以有多个,且每个可以同时处理多种异常;不必一定存在
else:在未捕获到异常时,进入else;else可可选的,不必一定存在
finaly:不论try有没有捕获到异常都会进入的块,这里很多同学没有深刻体会到它的用途,只是单纯认为,此关键字不是必须的,没有那么重要,这个是讨论的一点,帮助各位童鞋理解加深印象。
as:为各种异常进行一个起别名额功能。
1、首先执行try中的代码块(error_statement),如果代码执行过程中出现异常,python会立刻生成一个对应的异常对象,并且将该异常上报解释器,由解释器获得异常的过程,称之为==异常捕获==。
2、如果==捕获到异常==,会立刻进入异常处理流程(==此时在try中异常出现以后的代码不会再运行==),即except关键字引导的块,根据关键字后边的ExceptionName来==自上而下由左及右==地逐个检查是否有对应的异常名称,如果有则进入对应的except模块,执行==其中的do_Excepttion_statement代码块==;如果没有检测到匹配的异常名称则==不会进入任何except块==,代码会继续向下运行。
3、else流程:在try中未检测到任何异常才会进入else,童鞋们可能会有疑问?是没有检测到异常,还是except没有包含该异常?注意~~这是两个概念,前者是没有异常,后者是有异常但是没有进行except处理。答案是,没有检测到任何异常(代码完全OK)才会进入else。示例如下:
4、except流程:
此处主要强调在最上边例子中的except[(ExceptionName1,ExceptionName2 ...) [as ...]]:的理解,‘[ ]’上边提到过,是代表可以没有;那么,童鞋写了如下代码,看看两种代码的结果是否相同呢?
首先,需要搞清楚,代码二是有语法错误的,这个必须得改正,问题在于else不能和try搭配,只能和except;第二点,这个是重点,只写except和什么都不写之间有没有区别?答案是肯定的,什么都不写代表不进行处理,而只写 except :’ 相当于 ==‘except Exception:’,这种写法意思是说万能异常处理,即Exception这种异常是所有异常的统称,所以如上的代码一是势必会打印‘name is error’这句话。
5、finally流程(重点) :童鞋们往往在有些时候比较难理解finally的存在的意义,但是对于这样的流程,大家却都知道无论try是否捕获到异常,都会进入finally流程’;那么接下来,我们细细品一品这个sao气外漏的fianlly究竟为何如此之sao。
5.1 fianlly: 其实这玩意有个冠冕堂皇的功能:垃圾处理机制,说白了,如果你打开了一些物理文件,最终,是需要finally来进行关闭的(有同学就说了,那不写在finally里边不行吗,也可以。)
5.2究竟如何理解?示例如下:
5.3 总结:
当 try 块中代码发生异常,导致程序崩溃时,在崩溃前 Python 解释器也会执行 finally 块中的代码
如果你用 Python 编程,那么你就无法避开异常,因为异常在这门语言里无处不在。打个比方,当你在脚本执行时按 ctrl+c 退出,解释器就会产生一个 KeyboardInterrupt 异常。而 KeyError、ValueError、TypeError 等更是日常编程里随处可见的老朋友。
异常处理工作由“捕获”和“抛出”两部分组成。“捕获”指的是使用 try ... except 包裹特定语句,妥当的完成错误流程处理。而恰当的使用 raise 主动“抛出”异常,更是优雅代码里必不可少的组成部分。
异常分类
BaseException 所有异常的基类
Exception 常见错误的基类
ArithmeticError 所有数值计算错误的基类
Warning 警告的基类
AssertError 断言语句(assert)失败
AttributeError 尝试访问未知的对象属性
DeprecattionWarning 关于被弃用的特征的警告
EOFError 用户输入文件末尾标志EOF(Ctrl+d)
FloattingPointError 浮点计算错误
FutureWarning 关于构造将来语义会有改变的警告
GeneratorExit generator.close()方法被调用的时候
ImportError 导入模块失败的时候
IndexError 索引超出序列的范围
KeyError 字典中查找一个不存在的关键字
KeyboardInterrupt 用户输入中断键(Ctrl+c)
MemoryError 内存溢出(可通过删除对象释放内存)
NamerError 尝试访问一个不存在的变量
NotImplementedError 尚未实现的方法
OSError 操作系统产生的异常(例如打开一个不存在的文件)
OverflowError 数值运算超出最大限制
OverflowWarning 旧的关于自动提升为长整型(long)的警告
PendingDeprecationWarning 关于特征会被遗弃的警告
ReferenceError 弱引用(weak reference)试图访问一个已经被垃圾回收机制回收了的对象
RuntimeError 一般的运行时错误
RuntimeWarning 可疑的运行行为(runtime behavior)的警告
StopIteration 迭代器没有更多的值
SyntaxError Python的语法错误
SyntaxWarning 可疑的语法的警告
IndentationError 缩进错误
TabError Tab和空格混合使用
SystemError Python编译器系统错误
SystemExit Python编译器进程被关闭
TypeError 不同类型间的无效操作
UnboundLocalError 访问一个未初始化的本地变量(NameError的子类)
UnicodeError Unicode相关的错误(ValueError的子类)
UnicodeEncodeError Unicode编码时的错误(UnicodeError的子类)
UnicodeDecodeError Unicode解码时的错误(UnicodeError的子类)
UserWarning 用户代码生成的警告
ValueError 传入无效的参数
ZeroDivisionError 除数为零
Python中异常重试的解决方案详解
大家在做数据抓取的时候,经常遇到由于网络问题导致的程序保存,先前只是记录了错误内容,并对错误内容进行后期处理。
原先的流程:
def crawl_page(url):
pass
def log_error(url):
pass
url = ""
try:
crawl_page(url)
except:
log_error(url)
改进后的流程:
attempts = 0
success = False
while attempts 3 and not success:
try:
crawl_page(url)
success = True
except:
attempts += 1
if attempts == 3:
break
最近发现的新的解决方案:retrying
retrying是一个 Python的重试包,可以用来自动重试一些可能运行失败的程序段。retrying提供一个装饰器函数retry,被装饰的函数就会在运行失败的条件下重新执行,默认只要一直报错就会不断重试。
import random
from retrying import retry
@retry
def do_something_unreliable():
if random.randint(0, 10) 1:
raise IOError("Broken sauce, everything is hosed!!!111one")
else:
return "Awesome sauce!"
print do_something_unreliable()
如果我们运行have_a_try函数,那么直到random.randint返回5,它才会执行结束,否则会一直重新执行。
retry还可以接受一些参数,这个从源码中Retrying类的初始化函数可以看到可选的参数:
stop_max_attempt_number:用来设定最大的尝试次数,超过该次数就停止重试
stop_max_delay:比如设置成10000,那么从被装饰的函数开始执行的时间点开始,到函数成功运行结束或者失败报错中止的时间点,只要这段时间超过10秒,函数就不会再执行了
wait_fixed:设置在两次retrying之间的停留时间
wait_random_min和wait_random_max:用随机的方式产生两次retrying之间的停留时间
wait_exponential_multiplier和wait_exponential_max:以指数的形式产生两次retrying之间的停留时间,产生的值为2^previous_attempt_number * wait_exponential_multiplier,previous_attempt_number是前面已经retry的次数,如果产生的这个值超过了wait_exponential_max的大小,那么之后两个retrying之间的停留值都为wait_exponential_max。这个设计迎合了exponential backoff算法,可以减轻阻塞的情况。
我们可以指定要在出现哪些异常的时候再去retry,这个要用retry_on_exception传入一个函数对象:
def retry_if_io_error(exception):
return isinstance(exception, IOError)
@retry(retry_on_exception=retry_if_io_error)
def read_a_file():
with open("file", "r") as f:
return f.read()
在执行read_a_file函数的过程中,如果报出异常,那么这个异常会以形参exception传入retry_if_io_error函数中,如果exception是IOError那么就进行retry,如果不是就停止运行并抛出异常。
我们还可以指定要在得到哪些结果的时候去retry,这个要用retry_on_result传入一个函数对象:
def retry_if_result_none(result):
return result is None
@retry(retry_on_result=retry_if_result_none)
def get_result():
return None
在执行get_result成功后,会将函数的返回值通过形参result的形式传入retry_if_result_none函数中,如果返回值是None那么就进行retry,否则就结束并返回函数值。
可能触发异常产生的代码会放到try语句块里,而处理异常的代码会在except语句块里实现。例如:
我们可以使用三种方法来处理多个异常。
第一种方法需要把所有可能发生的异常放到一个元组里。像这样:
另外一种方式是对每个单独的异常在单独的except语句块中处理。我们想要多少个except语句块都可以:
最后一种方式会捕获 所有 异常:
注意,捕获所有异常可能会造成意外的结果,比如,通常我们使用CTRL+C来终止程序,但如果程序中捕获了所有异常,CTRL+C就无法终止程序了。
包裹到finally从句中的代码不管异常是否触发都将会被执行。这可以被用来在脚本执行之后做清理工作:
如果想在没有触发异常的时候执行一些代码,可以使用else从句。
有人也许问了:如果你只是想让一些代码在没有触发异常的情况下执行,为啥你不直接把代码放在try里面呢?回答是,那样的话这段代码中的任意异常都还是会被try捕获,而你并不一定想要那样。
else从句只会在没有异常的情况下执行,而且它会在finally语句之前执行。