11

我创建了一堆函数,我需要非常相似的 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 语句,这样它们就不会让我的代码看起来那么拥挤。有没有好的方法来做到这一点?

4

5 回答 5

24

Python 装饰器是你想要的。

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

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


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

在应用了装饰器的情况下调用方法时:

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

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

于 2012-02-21T22:53:27.460 回答
7

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

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 
于 2014-07-12T10:08:06.323 回答
6

块内的内容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)
于 2012-02-21T22:58:56.403 回答
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: 问题

于 2012-02-21T23:11:27.200 回答
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

希望这有帮助!

于 2017-05-12T07:49:54.027 回答