You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Flask Session存储含Feature字段数据时返回Null问题求助

解决Flask Session存入长Feature字符串后返回Null的问题

嘿,我太懂你这糟心的情况了——把亚马逊商品的Feature字段(就是那串超长的商品描述)存入Flask Session后,在/profile/<asin>路由里取数据居然返回null,但只要删掉Feature键值对,Session立马恢复正常,价格啥的都能正常读取。而且你已经确认Feature是普通字符串,逻辑也没问题,对吧?

代码重现

存入Session的核心代码

app = Flask(__name__)
app.config['SECRET_KEY'] = 'yo'
@app.route('/', methods=['GET','POST'])
def index():
    authenticated_url = authenticate(Availability='Available',Operation='ItemSearch',Keywords=str(query),SearchIndex='Electronics', ResponseGroup='ItemAttributes')
    product = authenticated_url['ItemSearchResponse']['Items']['Item']
    arr = []
    for items in product:
        main_dictionary = {}
        sub_dictionary = {}
        sub_dictionary['price'] = items['ItemAttributes']['FormattedPrice']
        featureLists = items['ItemAttributes']['Feature']
        emptyFeatureStr = ' '
        for items in featureLists:
            emptyFeatureStr += items
        sub_dictionary['Feature']=emptyFeatureStr
        main_dictionary[items['ASIN']]=sub_dictionary # 构建以ASIN为键的字典
        arr.append(main_dictionary) # 将字典存入数组
    session['searchResults']=arr
    print(session['searchResults']) # 确认此处session已正确设置,字典符合预期

读取Session的路由代码

@app.route('/profile/<asin>', methods=['GET','POST'])
def profilePage(asin):
    return str(session.get('searchResults'))

问题根源

Flask默认的Session是基于Cookie的客户端Session——它会把Session数据加密后存在用户浏览器的Cookie里,而Cookie有严格的大小限制(一般是4KB左右)。你传入的Feature字符串实在太长了,拼接后的数据量直接突破了这个限制,导致整个Session数据没法正常写入Cookie,甚至被截断,所以读取的时候就返回了null。而去掉Feature后,Session的数据量刚好卡在Cookie限制范围内,自然就正常工作了。

解决方案

方案一:改用服务器端Session(最推荐)

Flask-Session扩展把Session数据存在服务器端(比如Redis、Memcached或者本地文件),彻底摆脱Cookie的大小限制。

操作步骤:

  1. 安装Flask-Session:
pip install flask-session
  1. 修改Flask配置(以Redis为例,没有Redis的话可以用filesystem类型存在本地文件):
from flask import Flask, session
from flask_session import Session
import redis

app = Flask(__name__)
app.config['SECRET_KEY'] = 'yo'
# 配置Session存储类型为Redis
app.config['SESSION_TYPE'] = 'redis'
# 连接本地Redis服务,根据你的实际环境修改地址和端口
app.config['SESSION_REDIS'] = redis.Redis(host='localhost', port=6379)
# 初始化Session
Session(app)

# 后续路由代码无需修改,保持原来的逻辑即可

方案二:把长字符串存入数据库,Session仅存标识

如果不想用扩展,可以把Feature的长字符串存入数据库(比如SQLite、MySQL),Session里只存ASIN和对应的数据库记录ID,需要展示Feature时再从数据库查询。

方案三:压缩长字符串(临时缓解,不推荐长期使用)

如果一定要用客户端Session,可以尝试用zlib压缩Feature字符串来减小体积:

import zlib
import base64

# 存入Session时压缩
compressed_feature = base64.b64encode(zlib.compress(emptyFeatureStr.encode())).decode()
sub_dictionary['Feature'] = compressed_feature

# 读取Session时解压
compressed_feature = session_data['Feature']
original_feature = zlib.decompress(base64.b64decode(compressed_feature)).decode()

不过这个方法只是权宜之计,如果字符串实在太长,压缩后还是超过Cookie限制,就没用了,所以优先选方案一。

内容的提问来源于stack exchange,提问作者Biplov

火山引擎 最新活动