[PYTHON] Wie man eine schreckliche Bibliothek austrickst und benutzt, die global in einer Flasche aufbewahrt werden soll

Einführung

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 auf global stellen

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

Schnittstelle ähnlich dem lokalen Thread-Objekt

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

Wenn der Initialisierungsprozess Zeit braucht

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.

Bonusgeschichte

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

Recommended Posts

Wie man eine schreckliche Bibliothek austrickst und benutzt, die global in einer Flasche aufbewahrt werden soll
So verwenden Sie eine Bibliothek, die ursprünglich nicht in Google App Engine enthalten war
Verwendung ist und == in Python
Verwendung von hmmlearn, einer Python-Bibliothek, die versteckte Markov-Modelle realisiert
Verwendung der C-Bibliothek in Python
Verwendung der Python-Bildbibliothek in der Python3-Serie
Tipps für diejenigen, die verwirrt sind, wie man is und == in Python verwendet
So installieren Sie die Python-Bibliothek, die von Pharmaunternehmen verwendet werden kann
Ein Memorandum zur Verwendung von Keras 'keras.preprocessing.image
So überprüfen Sie, ob es sich um einen Wörterbuch-Typ (Wörterbuch, Hash) handelt, indem Sie einen oder alle verwenden
Hinweise zur Verwendung von StatsModels, die lineare Regression und GLM in Python verwenden können
Verwendung von Docker zum Containerisieren Ihrer Anwendung und Verwenden von Docker Compose zum Ausführen Ihrer Anwendung in einer Entwicklungsumgebung
[C / C ++] Übergeben Sie den in C / C ++ berechneten Wert an eine Python-Funktion, um den Prozess auszuführen, und verwenden Sie diesen Wert in C / C ++.
So richten Sie einen einfachen SMTP-Server ein, der lokal in Python getestet werden kann
[Python] Was ist ein Tupel? Erklärt, wie man es benutzt und wie man es benutzt, ohne zu tippen.
Es kann ein Problem sein, Japanisch für Ordnernamen und Notizbuchnamen in Databricks zu verwenden
So testen Sie, ob die Ausnahme in Python unittest ausgelöst wird
Verwendung der Methode __call__ in der Python-Klasse
Wie Sie pyenv und pyenv-virtualenv auf Ihre eigene Weise verwenden
[Einführung in die Udemy Python3 + -Anwendung] 36. Verwendung von In und Not
Erstellen und Verwenden von statischen / dynamischen Bibliotheken in C-Sprache
Vergleich der Verwendung von Funktionen höherer Ordnung in Python 2 und 3
So schreiben Sie eine Meta-Klasse, die sowohl Python2 als auch Python3 unterstützt
Hinweise zur Verwendung von Marshmallow in der Schemabibliothek
So vergleichen Sie Listen und rufen allgemeine Elemente in einer Liste ab
Verwenden Sie networkx, eine Bibliothek, die Diagramme in Python verarbeitet (Teil 2: Lernprogramm).
Geben und meinen Sie die Einschränkungsoption in scipy.optimize.minimize
Verwendung von Funktionen in separaten Dateien Perl-Version und Python-Version
So stellen Sie fest, dass in Python3 ein Kreuzschlüssel eingegeben wurde
Verwendung von Sternchen (*) in Python. Vielleicht ist das alles? ..
Ist Rs do.call () eine klassische Funktion höherer Ordnung? Erfahren Sie, wie man es benutzt
[Ln] Das Einfügen des symbolischen Links des Verzeichnisses ist kompliziert
Verwendung von Klassen in Theano
Verwendung von .bash_profile und .bashrc
So installieren und verwenden Sie Graphviz
Wie man MySQL mit Python benutzt
Verwendung von ChemSpider in Python
Verwendung von PubChem mit Python
So geben Sie eine Zeichenfolge in Python ein und geben sie unverändert oder in die entgegengesetzte Richtung aus.
CNN bestimmt, an welcher Universität eine schöne Frau wahrscheinlich sein wird
So erhalten Sie mit pandas DataFrame einen bestimmten Spaltennamen und Indexnamen
Wie man einen Janken-Bot macht, der leicht bewegt werden kann (Kommentar)
So setzen Sie in Python ein Leerzeichen mit halber Breite vor Buchstaben und Zahlen.
So machen Sie den Containernamen in Docker als Subdomain zugänglich
Was ist eine C-Sprachbibliothek? Welche Informationen sind für die Öffentlichkeit zugänglich?
Bequem zum Verwenden von Ebenen beim Laden von Bibliotheken auf Lambda
So stoppen Sie das Programm bis zu einem bestimmten Datum und einer bestimmten Uhrzeit in Python
So speichern Sie die Feature-Point-Informationen des Bildes in einer Datei und verwenden sie zum Abgleichen
Ich dachte, es wäre langsam, die for-Anweisung in NumPy zu verwenden, aber das war nicht der Fall.
Verwendung berechneter Spalten in CASTable
[Einführung in Python] Wie verwende ich eine Klasse in Python?
So teilen und speichern Sie einen DataFrame
So installieren und verwenden Sie pandas_datareader [Python]
[Pandas] Was ist set_option?
Verwendung von Google Test in C-Sprache
Wie bekomme ich Stacktrace in Python?
Mindestkenntnisse zur Verwendung von Form with Flask
Verwendung von Anacondas Interpreter mit PyCharm
Python: Verwendung von Einheimischen () und Globalen ()
Verwendung von __slots__ in der Python-Klasse