2011-10-21 10 views
5

YAML ve SQLAlchemy kullanıyorum. Nesnemi tanımladım ve YAML'i sadece iyi yazdırmak için kullanabiliyorum. Ancak, bir SQLAlchemy sorgusundan döndürülen nesne üzerinde YAML kullanmaya çalıştığımda, can't pickle int objects hatasıyla başarısız oluyor. SQLAlchemy'den döndürülen örneği yazdırdım ve doğru türünü gösteriyor. Ben kod let konuşma yapmak:Nesne SQLAlchemy'den geldiğinde int nesnesi hatası alamıyor musunuz?

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:[email protected]/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

"Örnek" türü nedir? Bir yaml.dump (10) iyi çalışıyor, bu yüzden gerekli pickling yöntemine sahip olmayan bir SQLAlchemy türü olabilir (ör.kendisi tarafından seçilebilir türleri döndüren bir __reduce__ yöntemi). –

cevap

2

deneyin sınıflarına aşağıdaki ekleyerek:

def __reduce__(self): 
    'Return state information for pickling' 
    return self.__class__, (int(self.hash_code), str(self.file_pointer)) 
+1

Baskı (yaml.dump (fhash)) düzgün çalıştığı için kafam karıştı, bu yüzden orada şikayetçi değil. Neden bir sorgudan geldiğinde yazı tipi değişir? – esac

+0

"Yazdırma örneği" nden sonra "yazdırma tipi (örnek)" yazın. Ne alıyorsun? –

+0

baskı '' – esac

1

Varsayılan reduce_ex yöntemi (im oldukça emin bu biridir çıkıyor sqlalchemy etkinken satırdan aşağıya inen)(), satır içinde aşağıya iner, _sa_instance_state üyesi, PyYAML'nin seri hale getirme için kullandığı reduction_ex API'sinde döndürülen 'duruma' eklenir.

SqlAlchemy sorgusundan gelen bir nesneyi serileştirirken, bu aslında nesnenin meta verilerinin gizli bir parçasıdır ve bu işlem başka işlemlere açık olur.

PyYAML seri hale getiricisinin başarısız olduğu bu nesnedir. Bu dizininizi PDB'de çalıştırarak ve göreceli olarak basit SQLAlchemy sorgu nesnesi sonuçları için bile çağrı yığınınızda, temsilci_object için iki çağrısını görerek bunu doğrulayabilirsiniz.

Bu sorgu örneği bağlantısı, anladığım gibi, aynı python yorumlayıcısının yaşam süresi içinde belirli bir nesneyi oluşturan sorguyu geri sorgulayabilmenizi sağlayan güç yöntemleriyle kullanılır.

Eğer bu işlevsellikle ilgileniyorsanız (session.new & session.dirty gibi), PyYAML diziselleştiricisinde bunun için destek almanız gerekir. Bu aynı zamanda SQLAlchemy serileştirici uzantısını kıracak unutmayın - umursamıyorsun ve sadece beyan üyeleri istiyorsanız

, sen * azaltmak çağrıları o askıyı gizler 'bir temel sınıf kullanabilirsiniz iyi olsa da, planlarınızı dikkatlice değerlendirin. bu değişikliği uygulamak için

bir temel sınıfın bir örneği: Bu daha sonra gidiş-dönüş onları ilişkisini olsa Eğer askıda işlemlerden, In/YAML dışı Nesnelerinizi gidiş dönüş sağlayacak

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 

veya sorguları. Bir örnek için tembel yüklü üyeler kullanıyorsanız, bu da etkileşimlere sahip olabilir. Beklediğiniz her şeyi serileştirdiğinizden emin olun./DÜZENLEME

NOT: Mümkün diğer temel sınıflar veya Mixins ile uyumlu olacak şekilde, burada reduce_ex kullanmayı tercih etti. https://docs.python.org/2/library/pickle.html#object.reduce_ex'a göre, bu, yalnızca 'un() öğesinin azaltıp azaltmadığını belirleyen herhangi bir temel sınıf için doğru davranışı üretecektir.

Redux ... örnek nesnenin gerçek dicti dönecektir azaltmak - biz oradan silmek istemiyoruz, __reduce * için çok, biz gerektiğini aslında sığ kopya olduğunu dict.