Работая с глобальным синглтоном во Flask (WSGI), нужно ли мне беспокоиться о состоянии гонки?

Привет мир демо для Flask это:

from flask import Flask
app = Flask(__name__)

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

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

Что делать, если я изменил это так:

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

Я понимаю, что приложение WSGI может иметь несколько потоков. hello Функция может выполняться одновременно на нескольких потоках, и тогда у нас будет условие гонки. Это правильно? Если приведенный выше код не является потокобезопасным, что я могу сделать, чтобы сделать его потокобезопасным?

Избегание глобальных изменений - это возможное решение, но всегда ли вы можете избежать глобальных? Что если я захочу что-то вроде кеша Python?

3 ответа

Решение

Вы можете использовать замок:

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

Вы можете попробовать локальный класс из werkzeug. Вот некоторая информация об этом: Местные жители контекста

Пример:

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

Вы могли бы взглянуть на g Объект, который вы можете импортировать непосредственно из колбы, сохраняет объект глобально для этого запроса. Если вы используете управляемый событиями WSGI-сервер (торнадо, gevent и т. Д.), У вас не должно возникнуть никаких проблем.

Другие вопросы по тегам