如何将SQLAlchemy记录对象存入Memcache?
解决SQLAlchemy对象存入Memcache变为字符串的问题
这个问题我之前也碰到过,本质是Memcache只能序列化存储简单数据类型(字符串、数字、字节流等),直接存入SQLAlchemy的ORM对象时,Memcache会自动调用对象的__repr__()方法把它转成字符串,所以取出来自然就是那个类似<__main__.Users object at 0x105b69b10>的字符串,而不是原来的User对象。
下面给你两种实用的解决方案:
方案一:用pickle序列化对象
Python自带的pickle工具可以把任意Python对象转成字节流,存入Memcache后再反序列化回来就能还原成原对象。
存入代码
import pickle from pymemcache.client.base import Client # 假设你的session和Users类已初始化完成 client = Client(('localhost', 11211)) user_obj = session.query(Users).get(1) # 把对象序列化成字节流 serialized_user = pickle.dumps(user_obj) client.set('testkey', serialized_user)
取出代码
import pickle from pymemcache.client.base import Client client = Client(('localhost', 11211)) serialized_user = client.get('testkey') if serialized_user: # 反序列化回原User对象 user_obj = pickle.loads(serialized_user)
⚠️ 注意:
- 要确保
Users类的定义在反序列化的环境中能正常导入,否则会报错。 pickle存在安全风险,如果Memcache中被存入恶意构造的字节流,反序列化可能执行恶意代码,所以不要在不可信的环境中使用。
方案二:转成字典存储(更安全可读)
如果不想用pickle,可以把ORM对象转成字典(只保留需要的字段),存入结构化的JSON字符串,可读性更好也更安全。
存入代码
from pymemcache.client.base import Client import json client = Client(('localhost', 11211)) user_obj = session.query(Users).get(1) # 提取对象的所有字段转成字典 user_dict = {col.name: getattr(user_obj, col.name) for col in user_obj.__table__.columns} # 转成JSON字符串存入Memcache client.set('testkey', json.dumps(user_dict))
取出代码
import json from pymemcache.client.base import Client client = Client(('localhost', 11211)) user_json = client.get('testkey') if user_json: user_dict = json.loads(user_json) # 可选:转回User对象(此时对象是脱管状态,需手动加入session才能操作数据库) user_obj = Users(**user_dict)
顺便提下你初始SQLAlchemy代码的小问题
你代码里先绑定了DBSession.bind = engine,但engine是后面才创建的,这会导致绑定失败,正确的顺序应该是:
from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker # 先创建engine engine = create_engine('mysql://root:password@localhost/db', echo=True) # 初始化Base Base = declarative_base(engine) # 初始化sessionmaker并绑定engine DBSession = sessionmaker(bind=engine) # 创建session实例 session = DBSession() class Accounts(Base): __tablename__ = 'accounts' __table_args__ = {'autoload': True}
内容的提问来源于stack exchange,提问作者shakeel
相关产品推荐
相关产品推荐

