Python,有条件地使用装饰器(包没有安装在所有的env中)

时间:2018-03-10 00:04:54

标签: python decorator newrelic

我正在使用New Relic来监控我的Python(2.7)应用程序,但仅限于我的生产环境。我想使用他们的function_trace装饰器。

在wsgi.py中

try:
    import newrelic.agent
    newrelic.agent.initialize('/path/')
except Exception as e:
    pass

在views.py

if settings.ENV == "test":
    pass
else:
    import newrelic

@newrelic.agent.function_trace()
def my_function():
    ....

这在生产中效果很好,但当然在测试中失败了。我不能将if-else直接放在装饰器周围,所以我想我可以使用条件装饰器:

def newrelic_conditional_decorator(function)
    # What magic goes in here...
    if settings.ENV == "test":
        just return function
    else:
        use @newrelic.agent.function_trace() decorator

@newrelic_conditional_decorator
def my_function():
    ....

我总是对装饰者有点模糊,所以我希望在这里有所帮助! (或另一种处理测试中与生产中没有相同包的方法。)

1 个答案:

答案 0 :(得分:1)

装饰器接受一个函数并从中返回一个新函数。因此,如果你想要一个条件装饰器,你需要的只是当你不想应用装饰器时返回初始函数。

您的具体案例

def newrelic_conditional_decorator(function):

    if settings.ENV == "test":
        # We do not apply the decorator to the function
        return function
    else:
        # We apply the decorator and return the new function
        return newrelic.agent.function_trace()(function)

@newrelic_conditional_decorator
def my_function():
    ...

有点普遍性

你可以抽象这个来制作一个更通用的条件装饰器,它应用一个给定的生成器,前提是condition函数返回True

def conditional_decorator(decorator, condition, *args):

    def wrapper(function):
        if condition(*args):
            return decorator(function)
        else:
            return function

    return wrapper

@conditional_decorator(
    newrelic.agent.function_trace(),
    lambda settings: settings.ENV != "test",
    settings)
def my_function():
    ...
相关问题