我有以下代码:
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返回'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
,则两个方法都会返回栏。这里的错误是调用localhost:8888 / foo会在http响应和print函数中产生bar
。
答案 0 :(得分:14)
当您切换装饰器的顺序时,其他答案似乎缺少您将“bar”作为来自“/ foo”的响应。您必须在此使用@wraps
,除非您手动更新__name__
,__module__
等。 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)
答案 1 :(得分:2)
Flask的route
函数是一个注册函数,你将其称为副作用 - 它将为端点注册你的视图函数。但是,您只注册视图功能,而不是修饰视图功能。只需切换装饰器的顺序即可注册“时间跟踪”功能。
此外,您可以使用@ app.before_request和@ app.teardown_request注册的函数更可靠地跟踪时间(考虑到渲染模板所花费的时间等)。
答案 2 :(得分:0)
你为什么说你的装饰师不工作?
在你的第二个例子中,装饰器正在运行,这样一个简单的函数在0.035毫秒内执行是很现实的(3.5e-05是一个表示3.5倍10到-5的幂)。
作为参考,你需要颠倒两个装饰器顺序的原因是因为app.route
注册了它传递的函数。
因此你需要传递装饰函数,因此顺序。