重复尝试和除外条款

时间:2012-02-21 22:52:11

标签: python try-catch except

我已经创建了一堆函数,除了所有这些函数之外我需要非常相似,但是我讨厌有这么多行的try和除了子句以及每个函数内部相同的代码。例如:

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”之后的代码是相同的。我想整合除语句之外的那些,这样它们就不会让我的代码看起来如此狭窄。有没有办法做到这一点?

5 个答案:

答案 0 :(得分:22)

Python Decorators就是你想要的。

你说除了块总是一样的。制作一个可以满足您需求的自定义装饰器。你必须将它应用于每个函数/方法,但它肯定会保存重复。

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


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

调用应用装饰器的方法时:

>>> 
>>> example()
Oh noes
>>> 

您需要更改异常类型以及您所做的事情,但是您可以获得我的目标。

答案 1 :(得分:6)

try块内的内容是有趣的内容,因此应该在函数中。然后只需选择您想要的功能,并调用它,包含异常。您甚至可以将异常代码编写为函数,并将所选函数作为参数传递给它。 e.g。

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)

答案 2 :(得分:5)

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

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 :(得分:2)

如果这些是你的实际功能,那么很容易概括它们。

您可以创建一个通用功能

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:issue

答案 4 :(得分:0)

我最近遇到了同样的情况,在我的情况下,我有一些自定义异常,我需要进一步记录或提升异常。我已经创建了一个装饰器方法来处理各种类型的异常。

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

希望这有帮助!!