由于通讯机制的不同,导致flask-socketio与flask无法共用服务端会话,flask-socketio初始化时有个参数manage_session,默认是True,意思是由flask-socketio独立管理自己的会话,如果设置为False,则指明会话交由flask管理,但这仅限于共享,即在socketio建议连接之前由flask生成的会话,可以被socketio获取到,也可以在socketio内进行修改,但问题在于由socketio修改后的会话,却不能被flask监测并使用,即flask那边仍是原来的值,官方解释如下
💡我自己琢磨着,虽然可以共享了,但是会话数据仍然是各自存储,就像命名空间一样,各自互不影响,你能看到,只是使用了副本,并不是地址引用。
解决以上问题的核心关键,就是把会话数据存储在一个公用的地方,如文件,数据库等,大家都可以自由读写,这样就实现了会话共享。
一,安装flask-session
$ pip install Flask-Session
# 推荐使用redis存储,所以Redis扩展需要同步安装,或独立安装,以下命令可以同步安装
$ pip install "Flask-Session[redis]"
# 或单独安装
$ pip install Redis
# 其他可用存储类型请参阅 https://flask-session.readthedocs.io/en/latest/installation.html#available-storage-options
二,初始化配置
# 方式一,未使用蓝图项目,直接初始化
# project_dir/app.py,项目入口文件
from flask import Flask, session
from flask_session import Session
from flask_socketio import SocketIO
from redis import Redis
app = Flask(__name__)
# 设置session
app.config['SESSION_TYPE'] = 'redis'
app.config['SESSION_REDIS'] = Redis(host='localhost', port=6379, db=15)
app.config['SESSION_KEY_PREFIX'] = 'Flaskr'
Session(app)
socketio = SocketIO(app, cors_allowed_origins='*', manage_session=False) # , async_mode='eventlet'
@app.route('/set/')
def set():
session['key'] = 'value'
return 'ok'
@app.route('/get/')
def get():
return session.get('key', 'not set')
if __name__ == '__main__':
socketio.run(app, '0.0.0.0', debug=True)
# 方式二,使用蓝图项目,创建应用后再初始化
# project_dir/flaskr/__init__.py 项目工厂初始化文件
from flask import Flask
from flask_session import Session
from flask_socketio import SocketIO
from redis import Redis
# 全局实例化对象
socketio = SocketIO()
sess = Session()
def creat_app():
app = Flask(__name__, instance_relative_config=True, static_url_path='/flaskr/static')
# 设置session
app.config['SESSION_TYPE'] = 'redis'
app.config['SESSION_REDIS'] = Redis(host='localhost', port=6379, db=15)
app.config['SESSION_KEY_PREFIX'] = 'Flaskr'
# ...其他代码
# session初始化当前App
sess.init_app(app)
# socketIO初始化当前App
socketio.init_app(app, cors_allowed_origins='*', manage_session=False) # , async_mode='eventlet'
return app
# project_dir/app.py,项目入口文件
from flaskr import creat_app, socketio
app = creat_app()
if __name__ == '__main__':
socketio.run(app, '0.0.0.0', debug=True)
三,项目中使用
# flask路由中使用
@app.route('/set/')
def set():
session['key'] = 'AAA'
print(session.get('key'))
return 'ok'
# flask-socketio事件中使用
@socketio.on('connect')
def do_connect():
print(session.get('key'))
session['key'] = 'BBB'
print(session.get('key'))
return 'ok'
# 着重点是在socketio事件中,使用getattr调用某类某方法过程中产生的会话,可以同样在flask路由中获取并做修改
参考: