【问题标题】:Repetitive Try and Except Clauses重复尝试和除外条款
【发布时间】:2012-03-12 07:07:07
【问题描述】:

我创建了一堆函数,我需要在所有函数中都使用非常相似的 except 子句,但我讨厌有这么多行 try 和 except 子句以及每个函数内部的相同代码。例如:

import sys
import random

def foo():
    num=random.random()
    try:
        if num>0.5: print 'OK'
        elif num>0.25: raise NameError('Too Small')
        else: raise KeyboardInterrupt
    except NameError:
        print "%s had a NameError" % sys._getframe().f_code.co_name
    except:
        print "%s had a different Error" % sys._getframe().f_code.co_name

def bar():
    num=random.random()
    try:
        if num>0.8: print 'OK'
        elif num>0.6: raise NameError('Too Small')
        else: raise KeyboardInterrupt
    except NameError:
        print "%s had a NameError" % sys._getframe().f_code.co_name
    except:
        print "%s had a different Error" % sys._getframe().f_code.co_name

“try”后的代码因功能而异,但“except”后的代码相同。我想合并那些 except 语句,这样它们就不会让我的代码看起来那么拥挤。有什么好办法吗?

【问题讨论】:

  • 捕获任何异常通常是一个非常糟糕的主意。它掩盖了真正的问题并使调试更加困难。捕捉任何你知道的异常——如果你不知道它们,你真的想捕捉它们吗?
  • 这很好。如果函数失败,我确实需要脚本继续。最后一个“例外”包括print sys.exc_info()[:2],其中包括异常的名称。有没有更好的方法来做到这一点?

标签: python try-catch except


【解决方案1】:

Python Decorators 是你想要的。

你说 except 块总是一样的。制作一个可以做你想做的自定义装饰器。您必须将其应用于每个函数/方法,但它确实可以节省重复。

def handleError(function):
    def handleProblems():
        try:
            function()
        except Exception:
            print "Oh noes"
    return handleProblems


@handleError
def example():
   raise Exception("Boom!")

调用带有装饰器的方法时:

>>> >>> 示例() 哦不 >>>

您将需要更改异常类型以及您所做的事情,但您会明白我的目标。

【讨论】:

  • 这不是一个很好的例子,因为装饰器不适用于带参数的函数。
【解决方案2】:

上面的答案不适用于带参数的函数 - 对于后一种情况,我想你会想要这样的东西:

def handleError(f):
    def handleProblems(*args, **kwargs):
        try:
            return f(*args, **kwargs)
        except Exception:
            print "Oh noes"
    return handleProblems

我们可以这样测试:

@handleError
def addTwo(x, y): 
    print(x + y) 

>>> addTwo(5,5)
10
>>> addTwo(5, 's')
Oh noes 

【讨论】:

    【解决方案3】:

    try 块中的内容是有趣的东西,所以应该在函数中。然后只需选择您想要的函数并调用它,并由您的异常包装。您甚至可以将异常代码编写为函数,并将所选函数作为参数传递给 this。例如

    def foo():
        num=random.random()
        if num>0.5: print 'OK'
        elif num>0.25: raise NameError('Too Small')
        else: raise KeyboardInterrupt
    
    def bar():
        num=random.random()
        if num>0.8: print 'OK'
        elif num>0.6: raise NameError('Too Small')
        else: raise KeyboardInterrupt
    
    def try_numerics(f):
        try:
            f()
        except NameError:
            print "%s had a NameError" % sys._getframe().f_code.co_name
        except:
            print "%s had a different Error" % sys._getframe().f_code.co_name
    
    # In your main code...
    if (need_to_run_foo):
        try_numerics(foo)
    elif (need_to_run_bar):
        try_numerics(bar)
    

    【讨论】:

      【解决方案4】:

      如果这些是您的实际功能,则很容易概括它们。

      你可以创建一个通用函数

      def general(bottom_num, top_num):
        num=random.random()
        try:
          if num>top_num: print 'OK'
          elif num>bottom_num: raise NameError('Too Small')
          else: raise KeyboardInterrupt
        except NameError:
          print "%s had a NameError" % sys._getframe().f_code.co_name
        except:
          print "%s had a different Error" % sys._getframe().f_code.co_name
      

      这将防止您的代码重复并解决 try: except: 问题

      【讨论】:

        【解决方案5】:

        我最近遇到了同样的情况,在我的情况下,我有一些自定义异常,我需要根据这些异常记录或进一步引发异常。我创建了一个装饰器方法来按类型处理异常。

        try:
           obj.some_method()
        except Exception as e:
            catch_and_log_exception(e)
        
        
        def catch_and_log_exception(e):
            if isinstance(e, MyConnectionError):
                print "Connection error : %s." % e.message
                sys.exit(1)
            elif isinstance(e, MyConnectionTimeout):
                print "Connection to server has been timed out. %s" % e.message
                sys.exit(1)
            elif isinstance(e, MyException):
                message = e.explanation if e.explanation else e.message
                log_error_message(str(message))
                print "Failed, please check the logs."
                sys.exit(1)
            else:
                raise e
        

        希望有帮助!!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-10-23
          • 1970-01-01
          • 1970-01-01
          • 2020-12-17
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多