Flask里的定制装饰器坏了?

2024-05-21 05:31:39 发布

您现在位置:Python中文网/ 问答频道 /正文

我有以下代码:

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 -

怎么了?为什么我的装饰工不工作?

编辑

我觉得你们似乎看不出问题所在。

当我在@track_time_spent之前有@app.route时,两个方法都返回bar。这里的错误是调用localhost:8888/foo会在http响应和print函数中导致bar


Tags: nameappflaskdatetimereturnfootimedef
3条回答

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

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)

Flask的route函数是一个注册函数,因为它的副作用是您调用它-它将为端点注册您的view函数。但是,您只注册view函数,而不是修饰的视图函数。只需切换decorators的顺序来注册“时间跟踪”函数。

此外,您还可以使用@app.before廑request和@app.teardown廑request-registered函数更可靠地跟踪时间(考虑到呈现模板等所需的时间)。

你为什么说你的装修工不工作?

在第二个示例中,decorator正在运行,这样一个简单的函数将在0.035毫秒内执行是现实的(3.5e-05是一个表示法,表示3.5乘以10的幂为-5)。


作为参考,之所以需要颠倒两个decorator的顺序,是因为app.route注册了传递它的函数。

因此,您需要将修饰函数传递给它,从而传递顺序。

相关问题 更多 >