我正在开发一个使用sqlalchemy来提取大量数据的应用程序。应用程序对结果对象进行了大量计算,但从不对这些对象进行任何更改。应用程序太慢,并且分析表明花费大量时间来访问由sqlalchemy管理的属性。因此,我试图找出如何防止sqlalchemy检测这些对象。
到目前为止,我已基于this answer和this example取得了一些进展。我发现了两种不同的方法,但似乎没有一种方法可以用于人际关系。我大部分都是在没有全面了解sqlalchemy的内部结构的情况下进行的。在这两种情况下,我都使用以下测试会话和数据:
engine = create_engine('sqlite://')
engine.execute('CREATE TABLE foo (id INTEGER, name TEXT)')
engine.execute('INSERT INTO foo VALUES (0, \'Jeremy\')')
engine.execute('CREATE TABLE bar (id INTEGER, foo_id Integer)')
engine.execute('INSERT INTO bar VALUES (0, 0)')
engine.execute('INSERT INTO bar VALUES (1, 0)')
Session = sessionmaker(bind=engine)
session = Session()
然后我要么(1)使用InstrumentationManager的自定义子类:
class ReadOnlyInstrumentationManager(InstrumentationManager):
def install_descriptor(self, class_, key, inst):
pass
Base = declarative_base()
Base.__sa_instrumentation_manager__ = ReadOnlyInstrumentationManager
class Bar(Base):
__tablename__ = 'bar'
id = Column(Integer, primary_key=True)
foo_id = Column(Integer, ForeignKey('foo.id'))
class Foo(Base):
__tablename__ = 'foo'
id = Column(Integer, primary_key=True)
name = Column(String(32))
bars = relationship(Bar)
f = session.query(Foo).first()
print type(f.bars)
给出:
<class 'sqlalchemy.orm.relationships.RelationshipProperty'>
而不是预期的酒吧列表。
或者,(2)使用ClassManager的自定义子类:
class MyClassManager(ClassManager):
def new_instance(self, state=None):
if hasattr(self.class_, '__readonly_type__'):
instance = self.class_.__readonly_type__.__new__(self.class_.__readonly_type__)
else:
instance = self.class_.__new__(self.class_)
self.setup_instance(instance, state)
return instance
Base = declarative_base()
Base.__sa_instrumentation_manager__ = MyClassManager
class ReadonlyFoo(object):
pass
class ReadonlyBar(object):
pass
class Bar(Base, ReadonlyBar):
__tablename__ = 'bar'
__readonly_type__ = ReadonlyBar
id = Column(Integer, primary_key=True)
foo_id = Column(Integer, ForeignKey('foo.id'))
class Foo(Base, ReadonlyFoo):
__tablename__ = 'foo'
__readonly_type__ = ReadonlyFoo
id = Column(Integer, primary_key=True)
name = Column(String(32))
bars = relationship(Bar)
f = session.query(Foo).first()
print f.bars
给出:
AttributeError: 'ReadonlyFoo' object has no attribute 'bars'
有没有办法修改其中一种方法,以便关系仍然有效?或者,这个问题的另一种方法是否更好?