【问题标题】:Try-Except-Else-Finally return in else alternative?Try-Except-Else-Finally return in else Alternative?
【发布时间】:2017-02-11 15:43:38
【问题描述】:

我正在开发一个可以raise 多个Exceptions 的函数。我想在它们的 except 块中处理这些Exceptions,然后返回带有自定义消息和回溯的结果。问题是finally 是有保证的,所以我不能在else 块内返回任何东西。

如果引发了一些Exception,则此代码有效,但如果没有Exception,则此代码无效。在这种情况下,我只想返回{'success':True}

所以从这段代码:

def foo():
    try:
        #some code
        return {'success':True}
    except FirstException:
        tb = traceback.format_exc()
        msg = 'There was FirstExc'
        return {'success':False,
                'tb':tb,
                'msg':msg}
    except SecondException:
        tb = traceback.format_exc()
        msg = 'There was SecondExc'
        return {'success':False,
                'tb':tb,
                'msg':msg}
    ...

我不想重复returns。我试过了:

def foo():
    try:
        pass
    except FirstException:
        tb = traceback.format_exc()
        msg = 'There was FirstExc'
    except SecondException:
        tb = traceback.format_exc()
        msg = 'There was SecondExc'
    else:
        return {'success':True}
    finally:
        return {'success':False,
                'tb':tb,
                'msg':msg}

你知道怎么做吗?我知道我可以将return {'success':True} 放入try 块中,删除finallyelse 块并将return {'success':False,'tb':tb,'msg':msg} 添加到每个except 块中,但是有很多except 块,因此代码会重复多次.

还有其他选择吗?

【问题讨论】:

    标签: python python-2.7 exception


    【解决方案1】:

    不要使用finally 块。您只想为异常返回False,否则返回True;返回finally 始终适用于这两种情况。

    您可以从两个except 套房返回,也可以合并这两个套房。

    从两者返回会导致更多重复:

    def foo():
        try:
            pass
        except FirstException:
            tb = traceback.format_exc()
            msg = 'There was FirstExc'
            return {'success':False,
                    'tb':tb,
                    'msg':msg}
        except SecondException:
            tb = traceback.format_exc()
            msg = 'There was SecondExc'
            return {'success':False,
                    'tb':tb,
                    'msg':msg}
        else:
            return {'success':True}
    

    您可以将except 套件合二为一:

    def foo():
        try:
            pass
        except (FirstException, SecondException) as e:
            tb = traceback.format_exc()
            exception_type = 'FirstExc' if isinstance(e, FirstException) else 'SecondExc'
            msg = 'There was {}'.format(exception_type)
            return {'success':False,
                    'tb':tb,
                    'msg':msg}
        else:
            return {'success':True}
    

    另一种选择是先构建返回值,然后根据需要添加信息:

    def foo():
        result = {'success': True}
        try:
            pass
        except FirstException:
            tb = traceback.format_exc()
            msg = 'There was FirstExc'
            result = {'success': False, 'tb': tb, 'msg': msg}
        except SecondException:
            tb = traceback.format_exc()
            msg = 'There was SecondExc'
            result = {'success': False, 'tb': tb, 'msg': msg}
        finally:
            return result
    

    不过,这与 return-from-the-except-suite 选项并没有什么不同。

    【讨论】:

      【解决方案2】:
      def foo():
          success = False
          try:
              pass
          except FirstException:
              tb = traceback.format_exc()
              msg = 'There was FirstExc'
          except SecondException:
              tb = traceback.format_exc()
              msg = 'There was SecondExc'
          else:
              success = True
          finally:
              return {'success':success,
                      'tb':tb,
                      'msg':msg} if not success else {'success':success}
      

      替代方案:

      def foo():
          result = {"success": False}
          try:
              pass
          except FirstException:
              result['tb'] = traceback.format_exc()
              result['msg'] = 'There was FirstExc'
          except SecondException:
              result['tb'] = traceback.format_exc()
              result['msg'] = 'There was SecondExc'
          else:
              result['success'] = True
          finally:
              return result
      

      上述略有不同:

      def foo():
          result = {"success": False}
          try:
              pass
          except FirstException:
              result.update({'tb': traceback.format_exc(), 'msg': 'There was FirstExc'})
          except SecondException:
              result.update({'tb': traceback.format_exc(), 'msg': 'There was SecondExc'})
          else:
              result['success'] = True
          finally:
              return result
      

      【讨论】:

      • 条件表达式使这变得相当不可读。只需使用if not success: return {...},然后在下一行使用return {...}。无需使用else:
      • 会引发 NameError
      • @brunodesthuilliers:不,不会。如果successTrue,则条件表达式根本不会执行第一部分。 但是,由于在最后一行使用了条件表达式,所以很难看到。
      猜你喜欢
      • 2012-06-25
      • 1970-01-01
      • 1970-01-01
      • 2022-01-04
      • 2021-03-15
      • 2018-03-19
      • 2016-08-30
      • 1970-01-01
      相关资源
      最近更新 更多