2013-04-19 34 views
3

我有以下代码:烧瓶中的定制装饰器不工作?

import datetime 
from flask.app import Flask 

app = Flask(__name__) 
app.config.from_object(__name__) 
app.debug = True 

def track_time_spent(name): 
    def decorator(f): 
    def wrapped(*args, **kwargs): 
     start = datetime.datetime.now() 
     ret = f(*args, **kwargs) 
     delta = datetime.datetime.now() - start 
     print name, "took", delta.total_seconds(), "seconds" 
     return ret 
    return wrapped 
    return decorator 

@app.route('/foo') 
@track_time_spent('foo') 
def foo(): 
    print "foo" 
    return "foo" 

@app.route('/bar') 
@track_time_spent('bar') 
def bar(): 
    print "bar" 
    return "bar" 

我无法得到FOO返回 '富':

$ curl localhost:8888/foo 
bar 

(flask window) 
bar 
bar took 8.2e-05 seconds 
127.0.0.1 - - [18/Apr/2013 19:21:31] "GET /foo HTTP/1.1" 200 - 

$ curl localhost:8888/bar 
bar 

(flask window) 
bar 
bar took 3.5e-05 seconds 
127.0.0.1 - - [18/Apr/2013 19:21:35] "GET /bar HTTP/1.1" 200 - 

这是怎么回事?为什么我的装饰器不工作?

编辑

我不认为你们似乎能看出问题。

当我有@app.route@track_time_spent之前,方法返回吧。这里的错误是,在http响应以及打印功能中调用localhost:8888/foo导致bar

+0

你是什么意思“其他窗口”? –

+0

烧瓶不使用您直接写入的函数对象,而是将其存储到底层的werkzeug库中并根据请求调用它们。 – thkang

回答

10

当你切换装饰器的顺序时,其他答案似乎缺少你从“/ foo”得到“bar”的响应。除非您手动更新__name____module__等,否则您必须在此处使用@wraps。 Flask使用你的方法有点像单身人士,并且看到你的装饰器就像wrapped()方法,而不是你实际包装的方法。因此,你的路线将不断被最后一个使用装饰者的方法覆盖。

import datetime 
from functools import wraps 

from flask.app import Flask 

app = Flask(__name__) 
app.config.from_object(__name__) 
app.debug = True 


def track_time_spent(name): 
    def decorator(f): 
     @wraps(f) 
     def wrapped(*args, **kwargs): 
      start = datetime.datetime.now() 
      ret = f(*args, **kwargs) 
      delta = datetime.datetime.now() - start 
      print name, "took", delta.total_seconds(), "seconds" 
      return ret 
     return wrapped 
    return decorator 


@app.route('/foo') 
@track_time_spent('foo') 
def foo(): 
    print "foo" 
    return "foo" 


@app.route('/bar') 
@track_time_spent('bar') 
def bar(): 
    print "bar" 
    return "bar" 

app.run(host='0.0.0.0', port=8888) 
0

你为什么说你的修饰器不工作?

在第二个例子中,装饰在运行,这是现实,这样一个简单的功能将在0.035毫秒(3.5E-05是一种符号,这意味着3.5乘以10的-5次方)执行。


仅供参考,为什么你需要反转两个装饰的顺序的原因是因为app.route将注册在被传递的功能。

因此,你需要传递它的装饰功能,因此顺序。

+0

我声称我的装饰器不工作,因为访问/ foo返回'bar' – disappearedng

2

Flask's route函数是一种注册函数,您称其为副作用 - 它将为端点注册您的视图函数。但是,您只注册视图功能,而不是装饰视图功能。只需切换修饰器的顺序即可注册“时间跟踪”功能。另外,您可以使用@ app.before_request和@app.teardown_request注册的函数更加可靠地跟踪时间(考虑渲染模板所花费的时间等)。