我正在使用YAML和SQLAlchemy。我定义了我的对象,我能够使用YAML来打印就好了。但是,当我尝试对从SQLAlchemy查询返回的对象使用YAML时,它失败并显示错误can't pickle int objects
。我打印出从SQLAlchemy返回的实例,它显示的是正确的类型。我会让代码进行讨论:
class HashPointer(Base):
__tablename__ = 'hash_pointers'
id = Column(Integer, primary_key=True)
hash_code = Column(VARBINARY(64), unique=True)
file_pointer = Column(Text)
def __init__(self, hash_code, file_pointer):
self.hash_code = hash_code
self.file_pointer = file_pointer
def __repr__(self):
return "<HashPointer('%s', '%s')>" % (self.hash_code, self.file_pointer)
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
Engine = create_engine("mysql://user:pass@localhost/db", echo=True)
Session = sessionmaker(bind=Engine)
session = Session()
fhash = HashPointer(0x661623708235, "c:\\test\\001.txt")
# PRINTS FINE
print(yaml.dump(fhash))
for instance in session.query(HashPointer).all():
# PRINTS FINE AS __repr__
print instance
# THROWS ERROR, 'CAN'T PICKLE INT OBJECTS'
print(yaml.dump(instance))
答案 0 :(得分:2)
尝试将以下内容添加到您的课程中:
def __reduce__(self):
'Return state information for pickling'
return self.__class__, (int(self.hash_code), str(self.file_pointer))
答案 1 :(得分:1)
事实证明,默认的 reduce_ex 方法(我非常确定这是object()中的那个,但它并不一定是。)当你离开时让sqlalchemy有效,将_sa_instance_state
成员添加到&#39;州&#39;在 reduce_ex API中返回,PyYAML用它来执行序列化。
当序列化来自SqlAlchemy查询的对象时,这实际上是对象元数据的隐藏部分,可供进一步操作访问。
这是PyYAML序列化程序失败的对象。您可以通过在PDB中运行序列化来验证这一点,并在调用堆栈中看到两个调用represent_object,即使对于相对简单的SQLAlchemy查询对象结果也是如此。
正如我所理解的,这个查询实例链接用于为方法提供支持,让你回顾一下在同一个python解释器的生命周期内生成给定对象的查询。
如果您关心该功能(例如session.new&amp; session.dirty),您需要在PyYAML的序列化程序中实现对该功能的支持。
如果您不关心,只是想要宣传您的会员,您可以使用隐藏&#39;从调用 reduce * 的链接 - 请注意,这也会破坏SQLAlchemy序列化程序扩展,但请仔细考虑您的计划。
实现该更改的基类示例如下:
DeclBase = declarative_base()
class Base(DeclBase):
__abstract__ = True
def __reduce_ex__(self, proto):
ret = super(Base, self).__reduce_ex__(proto)
ret = ( ret[0], ret[1], dict(ret[2]) ) + ret[3:]
ret[2].pop('_sa_instance_state', None) # remove bad yamly from reduce state
return ret
这将允许您将对象往返于yaml中,但往返将使它们与任何待处理的事务或查询无关。如果你使用延迟加载的成员,这也可能有交互作为一个例子。确保序列化您期望的所有内容。
请注意/编辑: 我选择在这里使用 reduce_ex ,以与其他可能的基类或mixin兼容。根据{{3}},这将为任何基类产生正确的行为,同时检测是否只声明 reduce ()。
Redux ... reduce将返回实例对象的实际 dict - 我们不想从那里删除,所以对于__reduce *,我们实际上必须浅拷贝那个字典。