2012-04-16 3 views
13

monde bonjour démo pour Flask est:En travaillant avec un singleton global dans Flask (WSGI), dois-je m'inquiéter des conditions de course?

from flask import Flask 
app = Flask(__name__) 

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

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

si je modifié cela comme si:

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

Je comprends l'application WSGI pourrait avoir plusieurs threads. La fonction hello peut être exécutée sur plusieurs threads en même temps, puis nous avons une condition de concurrence. Est-ce correct? Si le code ci-dessus n'est pas sécurisé, que puis-je faire pour le rendre sûr?

Éviter les globals est une solution possible, mais pouvez-vous toujours éviter les globals? Que faire si je veux quelque chose comme un cache d'objets python?

Répondre

6

Vous pouvez utiliser un verrou:

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

Votre exemple (coupé et collé exactement) retourne 500 pour moi, car un est référencé avant l'affectation. – jeremyjjbrown

+0

Cela ne répond pas réellement à la question posée. Avez-vous besoin de verrouiller? Sous quelles conditions? Est-ce seulement pour les interprètes sans GIL? – Basic

0

Vous pouvez jeter un oeil à l'objet g que vous pouvez importer directement de flacon, conserve un objet globalement pour cette demande. Si vous utilisez un serveur WSGI piloté par un événement (tornado, gevent, etc.), vous ne devriez rencontrer aucun problème.

+4

Je pensais que l'objet 'g' gardait seulement l'état pendant une requête, et n'était donc pas utile pour l'utilisation ci-dessus. – osa

2

Vous pouvez essayer la classe locale de werkzeug. Voici quelques informations à ce sujet: Context Locals

Exemple:

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