我正在使用Flask,努力了解有关会话如何工作的详细信息,我正在使用:
烧瓶文档clearly states(粗体是我的):
会话对象的工作原理与普通字典非常相似, 跟踪修改的不同之处。
这是代理。
...
Section on proxies提到(再次,粗体是我的):
如果您需要访问权限 到被代理的基础对象,您可以使用
_get_current_object()
方法
因此,基础对象(session._get_current_object()
)必须保持与请求相同,或者如this answer and comment所建议的那样,保持不变。但是,它不会持久存在,也不会在内部请求或线程中存在。
这是一个演示代码:
import threading
from flask import (
Flask,
session,
)
app = Flask(__name__)
app.secret_key = 'some random secret key'
@app.route('/')
def index():
print("session ID is: {}".format(id(session)))
print("session._get_current_object() ID is: {}".format(id(session._get_current_object())))
print("threading.current_thread().ident is: {}".format(threading.current_thread().ident))
print('________________________________')
return 'Check the console! ;-)'
如果您将在上面运行Flask应用程序,并反复进入/
— session._get_current_object()
返回的ID有时会更改,而threading.current_thread().ident
则永远不会更改。
这使我提出以下问题:
session._get_current_object()
返回了什么恰好? session
代理基础的对象,但是该基础对象所绑定的对象(如果不是请求而不是线程,那么如果我希望它永远不会改变,那么对于上面的简单应用)?答案 0 :(得分:2)
session._get_current_object()
到底返回什么?
从技术上讲,它是名为LocalStack
的_request_ctx_stack
实例的最顶层元素的session
属性中引用的对象。
该堆栈的最上面的元素是在RequestContext
中实例化的Flask.wsgi_app
,每个HTTP请求都将调用该元素。
RequestContext
实现{{1}的方法}和push
本身与本地堆栈pop
之间的来回。 _request_ctx_stack
方法还针对上下文使用requesting a new session。
此会话是push
代理中可用的会话;通过session
代理可以使用RequestContext
初始化请求。这两个代理只能在请求上下文中使用,即正在处理活动的HTTP请求。
我得到它是一个基础会话代理的对象,但这是什么 底层对象绑定到(如果它不是请求而不是 线程,如果我希望它永远不会改变,那么简单 上面的应用程序)?
如上所述,由request
本地代理代理的请求上下文的会话属于session
。它随每个请求而变化。如Lifetime of the Context中所述,将为每个请求创建一个新上下文,并且每次执行RequestContext
时都会创建一个新会话。
push
的ID在连续请求之间保持不变可能是由于新会话对象是在与先前请求中的旧会话对象相同的内存地址中创建的。
另请参见:Flask文档的How the Context Works部分。
答案 1 :(得分:0)
import threading
from flask import (
Flask,
session,
request
)
app = Flask(__name__)
app.secret_key = 'some random secret key'
@app.route('/')
def index():
print(">>> session <<<")
session_id = id(session)
session_object_id = id(session._get_current_object())
print("ID: {}".format(session_id),
"Same as previous: {}".format(session.get('prev_sess_id', '') == session_id))
print("_get_current_object() ID: {}".format(session_object_id),
"Same as previous: {}".format(session.get('prev_sess_obj_id', '') == session_object_id))
session['prev_sess_id'] = session_id
session['prev_sess_obj_id'] = session_object_id
print("\n>>> request <<<")
request_id = id(request)
request_object_id = id(request._get_current_object())
print("request ID is: {}".format(request_id),
"Same as previous: {}".format(session.get('prev_request_id', '') == request_id))
print("request._get_current_object() ID is: {}".format(id(request._get_current_object())),
"Same as previous: {}".format(session.get('prev_request_obj_id', '') == request_object_id))
session['prev_request_id'] = request_id
session['prev_request_obj_id'] = request_object_id
print("\n>>> thread <<<")
thread_id = threading.current_thread().ident
print("threading.current_thread().ident is: {}".format(threading.current_thread().ident),
"Same as previous: {}".format(session.get('prev_thread', '') == thread_id))
session['prev_thread'] = thread_id
print('-' * 100)
return 'Check the console! ;-)'
唯一剩下的含糊之处是,为什么连续两次请求之间有时 session._get_current_object()
保持不变。根据{{3}}的建议(粗体是我的),它是:
可能,因为新会话对象是在与上一个请求中的旧会话对象相同的内存地址中创建的。