码迷,mamicode.com
首页 > 编程语言 > 详细

python中 try、except、finally执行顺序

时间:2018-12-14 19:53:24      阅读:252      评论:0      收藏:0      [点我收藏+]

标签:display   两种   影响   动作   spl   int   store   ide   exit   

我们虽然经常用到try...except 作为异常补货,但是其实很少去研究try源码和机制,也许点进去看过,也是看不出个所以然来

class Exception(BaseException):
    """ Common base class for all non-exit exceptions. """
    def __init__(self, *args, **kwargs): # real signature unknown
        pass

继承了BaseException

class BaseException(object):
    """ Common base class for all exceptions """
    def with_traceback(self, tb): # real signature unknown; restored from __doc__
        """
        Exception.with_traceback(tb) --
            set self.__traceback__ to tb and return self.
        """
        pass

    def __delattr__(self, *args, **kwargs): # real signature unknown
        """ Implement delattr(self, name). """
        pass

    def __getattribute__(self, *args, **kwargs): # real signature unknown
        """ Return getattr(self, name). """
        pass

    def __init__(self, *args, **kwargs): # real signature unknown
        pass
..................

 是不是仍然一脸懵逼,同感,哈哈,那还是直接上代码,事实大于雄辩

代码举例转自https://blog.csdn.net/u010159842/article/details/54924940 我觉得这个作者写的很清楚

一:在 try 中 raise一个异常,就立刻转入 except 中执行,在except 中遇到 return 时,就强制转到 finally 中执行, 在 finally 中遇到 return 时就返回,最终函数返回值是finally 返回的

ef test1():
   try:
      print(to do stuff)
      raise Exception(hehe)
      print(to return in try)
      return try
 except Exception:
      print(process except‘)return except
 finally:
      print(to return in finally)
      return finally

test1Return = test1()
print(test1Return :  + test1Return)
#输出:

#to do stuff
#process except
#to return in finally
#test1Return : finally

 

二:这里在 try 中没有抛出异常,因此不会转到 except 中,但是在try 中遇到return时,也会立即强制转到finally中执行,并在finally中返回

def test2():
   try:
      print(to do stuff)
      print(to return in try)
      return try
 except Exception:
      print(process except)
      print(to return in except)
      return except
 finally:
      print(to return in finally)
      return finally

test2Return = test2()
print(test1Return :  + test2Return)
#输出:
#to do stuff
#to return in try
#to return in finally
#test2Return : finally

 

test1和test2得到的结论:

无论是在try还是在except中,遇到return时,只要设定了finally语句,就会中断当前的return语句,跳转到finally中执行,如果finally中遇到return语句,就直接返回,不再跳转回try/excpet中被中断的return语句

def test3():
   i = 0
 try:
      i += 1
 print(i in try : %s%i)
      raise Exception(hehe)
 except Exception:
      i += 1
 print(i in except : %s%i)
      return i
      finally:
      i += 1
 print (i in finally : %s%i )

print(test3Return : %s% test3())
#输出:

#i in try : 1
#i in except : 2
#i in finally : 3
#test3Return : 2

 

 

def test4():
   i = 0
 try:
      i += 1
 return i
   finally:
      i += 1
 print (i in finally : %s%i )
print(test4Return : %s % test4())
#输出
#i in finally : 2
#test4Return : 1

 

test3和test4得到的结论:

在except和try中遇到return时,会锁定return的值,然后跳转到finally中,如果finally中没有return语句,则finally执行完毕之后仍返回原return点,将之前锁定的值返回(即finally中的动作不影响返回值),如果finally中有return语句,则执行finally中的return语句。

 

四:test5得到的结论:在一个循环中,最终要跳出循环之前,会先转到finally执行,执行完毕之后才开始下一轮循环

技术分享图片
def test5():
   for i in range(5):
      try:
         print(do stuff %s%i)
         raise Exception(i)
      except Exception:
         print(exception %s%i)
         continue
 finally:
         print(do finally %s%i)
test5()
输出

do stuff 0
exception 0
do finally 0
do stuff 1
exception 1
do finally 1
do stuff 2
exception 2
do finally 2
do stuff 3
exception 3
do finally 3
do stuff 4
exception 4
do finally 4
View Code

 

 

注:

python的错误也是class,所有的错误类型都继承自BaseException,各个类型的错误之间可能会存在继承关系,比如UnicodeError是ValueError的子类,
如果catch语句中同时出现了这两个错误,且UnicodeError在ValueError的后面处理的,那么永远都捕获不到UnicodeError。

python中内置的常用错误类型继承关系:

使用try…excetp捕获错误一个好处是,可以跨层调用,比如main()调用foo(),foo()调用bar(),而错误是在bar中出现的,最后我们只需要在main()中捕获就行。

五:举个工作中的例子

# 首先下面的代码是一段有问题的代码哦,是对try机制了解不清晰
import time
def pushMsg(ss):
    try:
        res=10/ss         # 设置报错点
        if res:
            return res
    except Exception as e:
        return False
# 该函数需求是调用pushMsg()函数,默认三次不成功返回,就不再调用
def exceptTest(ss):
    cnt = 1
    while cnt <= 3:
        try:
            res = pushMsg(ss)
            print("res:",res)
            if res:
                break    # 如果正常返回了,退出循环
        except Exception as e:
            print(e)
            continue   # 本意收集
        finally:
            cnt += 1
            time.sleep(1)
            print("cnt",cnt)
    if cnt > 3:
        print("3 times push failed!")
    return True

# 分两种情况(主要考量except和finall,在两层套用情况下执行顺序,也就是内层函数也用了try ,并且return False)
# 第一种:程序正常走下来,不设置错误 ss传值非零
ss=1
exceptTest(ss)
# 打印执行顺序:只有  res: 10.0,因为内外两层try ,都没有捕获到错误,except和finally 里面都没有执行打印,并且判断res有值就直接break退出循环了


# 第二种情况,置报错 ss传值为零
ss=0
exceptTest(ss)

# 打印执行顺序:下面的顺序,先打印了finally里面的内容,再打印了返回值res,但是!为什么except里面的东西没有打印呢!
"""
cnt 2
res: False
cnt 2
res: False
cnt 3
res: False
cnt 4
3 times push failed!
"""
# 总结上面两种情况,无论是有无异常,except里面的东西都没有执行,那外层的try根本没有用呀,这是为什么呢!
# 经过研究,发现内层函数pushMsg(ss),也用了try ,但是他直接return True或者False ,并没有把内层捕获到的错误传到外层,所以外层的try也就捕获不到异常了,y
# 外层函数就会默认没有错误,直接执行finally里面的内容
那么代码就可以这么改
def pushMsg(ss):
    try:
        res=10/ss         # 设置报错点
        if res:
            return res
    except Exception as e:
        import traceback
        traceback.print_exc()
        return False

def exceptTest(ss):

    cnt = 1
    while cnt <= 3:
        res = pushMsg(ss)
        print("res:", res)
        if res:
            break
        else:
            cnt += 1
            time.sleep(1)
    if cnt > 3:
        print("3 times push failed!")
    return True

 

python中 try、except、finally执行顺序

标签:display   两种   影响   动作   spl   int   store   ide   exit   

原文地址:https://www.cnblogs.com/zzy-9318/p/10120538.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!