Es gibt einige Bibliotheken, die global in Kolben verwendet werden sollen.
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) #Dies
@app.route("/")
def hello():
return hmm.hello() #Hier
if __name__ == "__main__":
app.run(port=4040)
Wenn man sich den Code im Inneren ansieht, scheint es, dass er die App nicht ersetzt und die App als Argument verwendet, weil sie Konfigurationsinformationen erhalten möchte. Ursprünglich möchte ich eine solche Bibliothek nicht benutzen. Möglicherweise müssen Sie es verwenden.
Die Implementierung selbst war wie folgt.
class Something(object):
def __init__(self, app=None):
self.init_app(app)
def init_app(self, app):
#Schauen Sie sich die Konfiguration an und tun Sie etwas
self.message = app.config["MESSAGE"]
def hello(self): #Die Methode, die Sie aufrufen möchten
return self.message
Ich möchte die App nicht direkt in global platzieren. Ich denke zum Beispiel, dass es normal ist, Blaupausen für die Definition der Ansicht zu verwenden. Wenn Sie es jedoch wie folgt umschreiben, tritt ein Problem auf.
views.py
from flask import Blueprint
b = Blueprint("hello", __name__)
@b.route("/")
def hello():
return hmm.hello() #Ich möchte das nennen
app.py
def make_app():
class settings:
MESSAGE = "hello from something"
app = Flask(__name__)
app.config.from_object(settings)
hmm = Something(app) #Es gibt keine Möglichkeit, dies zu berühren
app.register_blueprint(b)
return app
if __name__ == "__main__":
app = make_app()
app.run(port=4040)
Wenn Sie die App-Generierung in eine Funktion einbinden, können Sie nicht auf das gewünschte hmm zugreifen. Wenn Sie dagegen versuchen, hmm als Rückgabewert von make_app zurückzugeben, befindet es sich im selben Status wie die globale Variable und ist überwältigend.
thread local object
Es scheint, dass die Kultur des Kolbens darin besteht, ein fadenlokales Objekt zu verwenden. Das Anforderungsobjekt ist beispielsweise threadlokal. Es kann besser sein, dies auf folgende Weise zu tun. Übrigens, wenn Sie den Thread lokalisieren möchten, können Sie wie folgt vorgehen. current_app und g sind ebenfalls threadlokal.
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)
Es kann von 1 Anforderungen gemeinsam genutzt werden. Natürlich wird es jedes Mal neu generiert, wenn eine neue Anfrage eingeht. Sie können es nicht mögen.
Wenn Sie zweimal eine Anfrage an http: // localhost: 4040 / stellen, ist dies wie folgt.
hoi
hai
hoi
hai
Vielleicht möchten Sie wirklich einen Singleton haben. Es scheint die Kultur von flask zu sein, einen globalen Proxy zu veröffentlichen. Erstellen wir also ein Objekt mit einer ähnlichen Schnittstelle.
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)
Nur bei der ersten Anforderung generiert find_hmm ()
hmm.
Wenn Sie zweimal eine Anfrage an http: // localhost: 4040 / stellen, ist dies wie folgt.
hoi
hai
hai
Der Initialisierungsprozess kann einige Zeit dauern. Es kann zu aufwändig sein, den hmm-Proxy zum Zeitpunkt der Anforderung zu initialisieren (wenn auch nur zum ersten Mal). In einem solchen Fall ist es möglicherweise besser, einen Anwendungskontext zwangsweise zu erstellen und festzulegen.
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
Es ist möglicherweise einfacher, einen Kontext explizit zu erstellen, damit er mit current_app abgerufen werden kann, als sich zu bemühen, die App zu übergeben.
Das Erstellen eines neuen Kontexts kann auch beim Testen hilfreich sein. Wenn Sie beispielsweise den folgenden Code ausführen, wird nach Eingabe eines Werts in g.foo in f0 f0 aufgerufen, nachdem mit app_context () ein neuer Kontext erstellt wurde, sodass er im zweiten f1 None ist. ..
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()
Ergebnis
f0 before with
foo
f0 after with
None