2012-04-16 18 views
13

La demo hola mundo para Frasco es:Trabajando con un singleton global en Flask (WSGI), ¿tengo que preocuparme por las condiciones de carrera?

from flask import Flask 
app = Flask(__name__) 

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

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

¿Qué pasa si he modificado este 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() 

entiendo aplicación WSGI podría tener varios subprocesos. La función hello podría ejecutarse en varios subprocesos al mismo tiempo, y luego tendríamos una condición de carrera. ¿Es esto correcto? Si el código anterior no es seguro para subprocesos, ¿qué puedo hacer para que sea seguro?

Evitar los globales es una posible solución, pero ¿siempre se puede evitar los globales? ¿Qué sucede si quiero algo así como un caché de objetos de Python?

Respuesta

6

Se puede usar un bloqueo:

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

Su ejemplo (cortar y pegar exactamente) devuelve un 500 para mí, ya que una está referenciado antes de la asignación. – jeremyjjbrown

+0

Esto en realidad no responde la pregunta establecida. ¿Necesita _necesitar_ bloquear? ¿Bajo que condiciones? ¿Esto es solo para intérpretes sin GIL? – Basic

0

que te pueden echar un vistazo al objeto g que se puede importar directamente del frasco, mantiene un objeto a nivel mundial para esa solicitud. Si está utilizando un servidor WSGI basado en eventos (tornado, gevent, etc.) no debería tener ningún problema.

+4

Pensé que el objeto 'g' solo mantenía el estado durante una solicitud, y por lo tanto no era útil para el caso de uso anterior. – osa

2

Puede probar la clase Local desde werkzeug. Aquí hay algo de información al respecto: Context Locals

Ejemplo:

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