Certaines bibliothèques sont censées être utilisées globalement dans flask.
from flask import Flask
from something import Something
class settings:
MESSAGE = "hello from something"
app = Flask(__name__)
app.config.from_object(settings)
hmm = Something(app) #cette
@app.route("/")
def hello():
return hmm.hello() #ici
if __name__ == "__main__":
app.run(port=4040)
En regardant dans le code à l'intérieur, il semble qu'il ne se substitue pas à l'application et prend l'application comme argument parce qu'il veut obtenir des informations de configuration. À l'origine, je ne veux pas utiliser une telle bibliothèque. Vous devrez peut-être l'utiliser.
La mise en œuvre elle-même était la suivante.
class Something(object):
def __init__(self, app=None):
self.init_app(app)
def init_app(self, app):
#Regardez la configuration et faites quelque chose
self.message = app.config["MESSAGE"]
def hello(self): #La méthode que vous souhaitez appeler
return self.message
Je ne veux pas mettre l'application directement dans global. Par exemple, je pense qu'il est normal d'utiliser un plan pour la définition de la vue. Cependant, si vous le réécrivez comme suit, un problème se produira.
views.py
from flask import Blueprint
b = Blueprint("hello", __name__)
@b.route("/")
def hello():
return hmm.hello() #Je veux appeler ça
app.py
def make_app():
class settings:
MESSAGE = "hello from something"
app = Flask(__name__)
app.config.from_object(settings)
hmm = Something(app) #Il n'y a aucun moyen de toucher ça
app.register_blueprint(b)
return app
if __name__ == "__main__":
app = make_app()
app.run(port=4040)
Si vous encapsulez la génération d'application dans une fonction, il n'y a aucun moyen d'accéder au hmm que vous souhaitez utiliser. D'un autre côté, si vous essayez de renvoyer hmm comme valeur de retour de make_app, il sera dans le même état que la variable globale, et ce sera écrasant.
thread local object
Il semble que la culture de flask consiste à utiliser un objet local de thread. Par exemple, l'objet de requête est thread local. Il peut être préférable de le faire d'une manière qui suit ceci. À propos, si vous souhaitez rendre le thread local, vous pouvez procéder comme suit. current_app et g sont également des threads locaux.
from flask import g, current_app
from werkzeug.local import LocalProxy
def find_hmm():
print("hoi")
if not hasattr(g, "hmm"):
print("hai")
g.hmm = Something(current_app)
return g.hmm
hmm = LocalProxy(find_hmm)
Il peut être partagé entre 1 demandes. Bien sûr, il sera régénéré chaque fois qu'une nouvelle demande arrive. Cela ne vous plaira peut-être pas.
Si vous faites une demande à http: // localhost: 4040 / deux fois, ce sera comme suit.
hoi
hai
hoi
hai
Vous voudrez peut-être vraiment avoir un singleton. Cela semble être la culture de flask de publier un proxy global, alors créons un objet avec une interface similaire à la suite de cela.
class LazyOnceEvalObject(object):
def __init__(self, fn):
self._fn = fn
self.proxy = None
def __getattr__(self, name):
if self.proxy is None:
self.proxy = self._fn()
print("hai")
return getattr(self.proxy, name)
def find_hmm():
print("hoi")
return Something(current_app)
hmm = LazyOnceEvalObject(find_hmm)
Seulement à la première requête, find_hmm ()
générera hmm.
Si vous faites une demande à http: // localhost: 4040 / deux fois, ce sera comme suit.
hoi
hai
hai
Le processus d'initialisation peut prendre un certain temps. Il peut être trop fastidieux d'initialiser le proxy hmm au moment de la demande (mais seulement pour la première fois). Dans un tel cas, il peut être préférable de créer de force un contexte d'application et de le définir.
def make_app():
class settings:
MESSAGE = "hello from something"
app = Flask(__name__)
app.config.from_object(settings)
app.register_blueprint(b)
with app.app_context():
hmm.hello()
return app
Il peut être plus facile de créer explicitement un contexte afin qu'il puisse être récupéré avec current_app, plutôt que d'essayer de passer l'application.
La création d'un nouveau contexte peut également être utile lors des tests. Par exemple, si vous exécutez le code suivant, après avoir entré une valeur dans g.foo dans f0, f0 est appelée après avoir créé un nouveau contexte avec app_context (), donc ce sera None dans le second f1. ..
def f0():
g.foo = "foo"
print("f0 before with")
f1()
with current_app.app_context():
print("f0 after with")
f1()
def f1():
print(getattr(g, "foo", None))
with app.app_context():
f0()
résultat
f0 before with
foo
f0 after with
None
Recommended Posts