플라스크에서 글로벌 변수는 스레드 세이프입니까?요청 간에 데이터를 공유하려면 어떻게 해야 합니까?
제 애플리케이션에서는 요청을 함으로써 공통 객체의 상태가 변경되고 응답은 상태에 따라 달라집니다.
class SomeObj():
def __init__(self, param):
self.param = param
def query(self):
self.param += 1
return self.param
global_obj = SomeObj(0)
@app.route('/')
def home():
flash(global_obj.query())
render_template('index.html')
개발 서버에서 이것을 실행하면 1, 2, 3 등이 나올 것으로 예상됩니다.100명의 다른 고객들로부터 동시에 요청이 들어오면 뭔가 잘못될 수 있습니까?예상되는 결과는 100개의 서로 다른 클라이언트가 각각 1에서 100 사이의 고유한 숫자를 보는 것입니다.아니면 이런 일이 벌어질까요?
- 클라이언트 1 쿼리입니다.
self.param
는 1합니다. - 반환 문을 실행하기 전에 스레드가 클라이언트 2로 전환됩니다.
self.param
다시 증가합니다. - 스레드가 클라이언트 1로 다시 전환되고 클라이언트는 2번을 반환합니다.
- 이제 스레드가 클라이언트 2로 이동하여 3번을 반환합니다.
고객이 두 명밖에 없었기 때문에 예상 결과는 2와 3이 아닌 1과 2였습니다.숫자를 건너뛰었습니다.
애플리케이션을 확장할 때 실제로 이러한 현상이 발생합니까?글로벌 변수에 대한 대안은 무엇입니까?
글로벌 변수를 사용하여 이러한 데이터를 저장할 수 없습니다.스레드 안전하지 않을 뿐만 아니라 프로세스 안전하지 않을 뿐만 아니라 프로덕션 상태의 WSGI 서버는 여러 프로세스를 생성합니다.스레드를 사용하여 요청을 처리하는 경우 수가 틀릴 뿐만 아니라 요청을 처리한 프로세스에 따라 수가 달라집니다.
전역 데이터를 보관하려면 플라스크 외부의 데이터 원본을 사용합니다.데이터베이스, memcached 또는 redis는 모두 필요에 따라 적절한 별도의 스토리지 영역입니다.Python 데이터를 로드하고 액세스해야 하는 경우 고려하십시오. 사용자별로 간단한 데이터에 대해서도 세션을 사용할 수 있습니다.
개발 서버는 단일 스레드 및 프로세스에서 실행될 수 있습니다.각 요청이 동시에 처리되므로 설명한 동작을 볼 수 없습니다.스레드 또는 프로세스를 활성화하면 표시됩니다. app.run(threaded=True)
또는app.run(processes=10)
(1.0에서는 서버가 기본적으로 쓰레드화되어 있습니다.)
일부 WSGI 서버는 gevent 또는 다른 비동기 작업자를 지원할 수 있습니다.글로벌 변수는 여전히 대부분의 인종 조건에 대한 보호가 없기 때문에 스레드 세이프가 아닙니다.한 작업자가 값을 얻고, 산출하고, 다른 작업자가 수정하고, 산출하고, 산출하고, 첫 번째 작업자도 수정하는 시나리오가 있습니다.
요청 중에 일부 글로벌 데이터를 저장해야 하는 경우 Flask의 개체를 사용할 수 있습니다.또 다른 일반적인 경우는 데이터베이스 연결을 관리하는 최상위 개체입니다.이러한 유형의 "글로벌"은 각 요청에 고유하며 요청 간에 사용되지 않으며 리소스의 설정 및 해체를 관리하는 기능이 있습니다.
이것은 전 세계의 스레드 안전에 대한 대답이 아닙니다.
하지만 여기서 세션을 언급하는 것이 중요하다고 생각합니다.클라이언트별 데이터를 저장하는 방법을 찾고 있습니다.모든 연결은 스레드 안전한 방식으로 자체 데이터 풀에 액세스할 수 있어야 합니다.
이는 서버 측 세션에서 가능하며 매우 깔끔한 플라스크 플러그인으로 제공됩니다. https://pythonhosted.org/Flask-Session/
세션을 에는, A 을션설는경우하정세,,경우▁if▁a세▁sessions▁up는.session
변수는 모든 경로에서 사용할 수 있으며 사전처럼 작동합니다.이 사전에 저장된 데이터는 연결하는 각 클라이언트에 대해 개별적입니다.
다음은 간단한 데모입니다.
from flask import Flask, session
from flask_session import Session
app = Flask(__name__)
# Check Configuration section for more details
SESSION_TYPE = 'filesystem'
app.config.from_object(__name__)
Session(app)
@app.route('/')
def reset():
session["counter"]=0
return "counter was reset"
@app.route('/inc')
def routeA():
if not "counter" in session:
session["counter"]=0
session["counter"]+=1
return "counter is {}".format(session["counter"])
@app.route('/dec')
def routeB():
if not "counter" in session:
session["counter"] = 0
session["counter"] -= 1
return "counter is {}".format(session["counter"])
if __name__ == '__main__':
app.run()
나 뒤에pip install Flask-Session
당신은 이것을 실행할 수 있어야 합니다.다른 브라우저에서 액세스해 보십시오. 카운터가 서로 공유되지 않음을 알 수 있습니다.
요청 외부 데이터 원본의 다른 예로는 Flask-Caching 또는 다른 확장에서 제공하는 것과 같은 캐시가 있습니다.
common.py
그 과 같은을 넣으십시오.
from flask_caching import Cache
# Instantiate the cache
cache = Cache()
- 의 당이있파일이 .
flask app
생성되면 합니다.
# Import cache
from common import cache
# ...
app = Flask(__name__)
cache.init_app(app=app, config={"CACHE_TYPE": "filesystem",'CACHE_DIR': Path('/tmp')})
- 이제 캐시를 가져오고 다음과 같이 실행하여 응용 프로그램 전체에서 사용합니다.
# Import cache
from common import cache
# store a value
cache.set("my_value", 1_000_000)
# Get a value
my_value = cache.get("my_value")
이전에 발표된 답변을 전적으로 수용하고, 프로덕션 및 확장 가능한 Flask 스토리지에 글로벌 변수를 사용하지 않도록 하는 한편, 프로토타이핑 또는 정말 단순한 서버를 '개발 서버'라는 플라스크 아래에서 실행합니다.
...
저는 Python을 직접 했습니다.dict
Python 설명서에 따르면 스레드 세이프입니다.공정 안전하지 않습니다.
이러한 (서버 전역) 딕트의 삽입, 룩업 및 읽기는 개발 서버에서 실행되는 각 플라스크 세션(동시일 수 있음)에서 정상입니다.
이러한 글로벌 딕트가 고유한 Flask 세션 키로 키를 누르면 쿠키에 맞지 않는 세션별 데이터(최대 크기 4kB)의 서버 측 저장에 유용할 수 있습니다.
물론 이러한 서버 글로벌 명령어는 메모리 내에서 너무 크게 증가하지 않도록 주의해야 합니다.요청 처리 중에 '이전' 키/값 쌍이 만료되는 경우 코드화할 수 있습니다.
프로덕션 또는 확장 가능한 배포에는 권장되지 않지만, 별도의 데이터베이스가 지정된 작업에 너무 많은 로컬 작업 지향 서버에는 문제가 없을 수 있습니다.
...
언급URL : https://stackoverflow.com/questions/32815451/are-global-variables-thread-safe-in-flask-how-do-i-share-data-between-requests
'source' 카테고리의 다른 글
FlatButton 클릭 시 AlertDialog를 해제하는 방법은 무엇입니까? (0) | 2023.07.19 |
---|---|
선택을 사용하여 쿼리 결과에 행 추가 (0) | 2023.07.19 |
python에서 base 2에 로그인합니다. (0) | 2023.07.19 |
D3로 처리하기 위해 Nuxt.js 프레임워크에서 CSV 파일 가져오기 (0) | 2023.07.19 |
TypeScript의 개인 정적 속성 (0) | 2023.07.19 |