Работая с глобальным синглом в Flask (WSGI), мне нужно беспокоиться о состоянии гонки?
Демо-версия hello world для 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?
Ответы
Ответ 1
Вы можете использовать блокировку:
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()
Ответ 2
Вы можете попробовать локальный класс от 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()
Ответ 3
Вы можете взглянуть на объект g
, который вы можете импортировать непосредственно из фляги, сохраняет объект глобально для этого запроса. Если вы используете WSGI-сервер с событиями (торнадо, gevent и т.д.), У вас не должно быть проблем.