7 votes

Le décorateur personnalisé dans flask ne fonctionne pas ?

J'ai le code suivant :

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"

Je ne parviens pas à faire en sorte que foo renvoie '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 -

Que se passe-t-il ? Pourquoi mon décorateur ne fonctionne-t-il pas ?

EDITAR

Je ne pense pas que vous puissiez voir le problème.

Lorsque j'ai @app.route avant @track_time_spent , ambos retournent bar. L'erreur ici est que l'appel à localhost:8888/foo aboutit à bar dans la réponse http et dans la fonction d'impression.

19voto

TkTech Points 1082

Les autres réponses semblent ne pas tenir compte du fait que vous obtenez "bar" comme réponse à "/foo" lorsque vous inversez l'ordre des décorateurs. Vous devez utiliser @wraps à moins que vous ne mettiez à jour le __name__ , __module__ et ainsi de suite manuellement. Flask utilise vos méthodes un peu comme des singletons, et voit votre décorateur comme l'élément wrapped() au lieu des méthodes que vous avez enveloppées. Par conséquent, vos routes continueront à être écrasées par la dernière méthode à utiliser votre décorateur.

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)

3voto

tehasdf Points 142

Flask's route est une fonction d'enregistrement dans le sens où vous l'appelez pour son effet secondaire - elle enregistrera votre fonction de vue pour un point de terminaison. Cependant, vous n'enregistrez que la fonction de visualisation, pas la fonction décoré fonction de visualisation. Il suffit d'inverser l'ordre des décorateurs pour enregistrer la fonction "suivie dans le temps".

Vous pouvez également utiliser les fonctions @app.before_request et @app.teardown_request-registered pour suivre le temps de manière plus fiable (en tenant compte du temps nécessaire au rendu du modèle, etc.)

0voto

Thomas Orozco Points 15280

Pourquoi dites-vous que votre décorateur ne fonctionne pas ?

Dans votre deuxième exemple, le décorateur est en cours d'exécution, et il est réaliste qu'une fonction aussi simple s'exécute en 0,035 ms (3,5e-05 est une notation qui signifie 3,5 fois 10 à la puissance -5).


Pour mémoire, la raison pour laquelle vous avez dû inverser l'ordre des deux décorateurs est que app.route enregistre la fonction qui lui est transmise.

Il faut donc lui transmettre la fonction décorée, d'où l'ordre.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X