2012-04-16 3 views
13

Die Hallo Welt Demo für Flask ist:Wenn ich mit einem globalen Singleton in Flask (WSGI) arbeite, muss ich mich über die Rennbedingungen Gedanken machen?

from flask import Flask 
app = Flask(__name__) 

@app.route("/") 
def hello(): 
    return "Hello World!" 

if __name__ == "__main__": 
    app.run() 

Was passiert, wenn ich dies wie so geändert:

from flask import Flask 
app = Flask(__name__) 

a = 1 
b = 2 
c = 3 

@app.route("/") 
def hello(): 
    a += 1 
    b += a 
    c += b 
    return "Hello World!" 

if __name__ == "__main__": 
    app.run() 

ich WSGI Anwendung verstehen könnten mehrere Threads haben. Die hello-Funktion könnte gleichzeitig auf mehreren Threads ausgeführt werden, und dann hätten wir eine Racebedingung. Ist das richtig? Wenn der obige Code nicht Thread-sicher ist, was kann ich tun, um es threadsicher zu machen?

Die Vermeidung von Globalen ist eine mögliche Lösung, aber können Sie Globals immer vermeiden? Was ist, wenn ich etwas wie einen Python-Objektcache möchte?

Antwort

6

könnten Sie eine Sperre verwenden:

from threading import Lock 
from flask import Flask 
app = Flask(__name__) 

a = 1 
b = 2 
c = 3 
lock = Lock() 

@app.route("/") 
def hello(): 
    with lock: 
     a += 1 
     b += a 
     c += b 
    return "Hello World!" 

if __name__ == "__main__": 
    app.run() 
+3

Ihr Beispiel (geschnitten und geklebt genau) gibt ein 500 für mich, weil ein vor der Zuweisung referenziert wird. – jeremyjjbrown

+0

Dies beantwortet die gestellte Frage nicht wirklich. Müssen Sie sperren? Unter welchen Bedingungen? Ist das nur für Dolmetscher ohne GIL? – Basic

0

Sie vielleicht einen Blick auf das g Objekt nehmen, die Sie direkt von der Flasche importieren, halten ein Objekt global für diese Anforderung. Wenn Sie einen ereignisgesteuerten WSGI-Server (Tornado, Gevent usw.) verwenden, sollten Sie keine Probleme haben.

+4

Ich dachte, das 'g' Objekt behielt nur den Zustand während einer Anfrage und war daher für den obigen Anwendungsfall nicht nützlich. – osa

2

Sie könnten die Local-Klasse von werkzeug ausprobieren. Hier einige Informationen über sie: Context Locals

Beispiel:

from flask import Flask 
from werkzeug.local import Local 
app = Flask(__name__) 
loc = Local() 
loc.a = 1 
loc.b = 2 
loc.c = 3 

@app.route("/") 
def hello(): 
    loc.a += 1 
    loc.b += loc.a 
    loc.c += loc.b 
    return "Hello World!" 

if __name__ == "__main__": 
    app.run() 
Verwandte Themen