2012-04-16 7 views
13

Il ciao mondo demo di Flask è:Lavorando con un singleton globale in Flask (WSGI), devo preoccuparmi delle condizioni di gara?

from flask import Flask 
app = Flask(__name__) 

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

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

Che cosa succede se ho modificato questo modo:

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() 

Capisco applicazione WSGI potrebbe avere più thread. La funzione hello potrebbe essere in esecuzione su più thread contemporaneamente e quindi avremmo una condizione di competizione. È corretto? Se il codice sopra non è thread-safe, cosa posso fare per renderlo thread-safe?

Evitare le globali è una possibile soluzione, ma puoi sempre evitare i globali? Cosa succede se voglio qualcosa di simile a una cache di oggetti Python?

risposta

6

Si potrebbe utilizzare una serratura:

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

Il vostro esempio (tagliato e incollato esattamente) restituisce un 500 per me, perché una si faccia riferimento prima assegnazione. – jeremyjjbrown

+0

Questo in realtà non risponde alla domanda indicata. Hai bisogno di bloccare? In quali condizioni? È solo per interpreti senza GIL? – Basic

0

si potrebbe dare un'occhiata al l'oggetto g che è possibile importare direttamente dalla boccetta, mantiene un oggetto a livello globale per quella richiesta. Se stai usando un server WSGI event driven (tornado, gevent, ecc) non dovresti avere problemi.

+4

Ho pensato che l'oggetto 'g' stava solo mantenendo lo stato durante una richiesta, e quindi non era utile per il caso precedente. – osa

2

Si potrebbe provare la classe locale da werkzeug. Ecco alcune informazioni su di esso: Context Locals

Esempio:

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() 
Problemi correlati