"de-instrument"来自sqlalchemy ORM的实例化对象

Joh*_*ohn 4 python optimization sqlalchemy

是否有一种简单的方法可以"解除"来自sqlalchemy的ORM的实例化类,即将其转换为常规对象?

即,假设我有一个映射到工作表的Worker类:

class Worker(object):
      def earnings(self):
          return self.wage*self.hours 

mapper(Worker,workers)
Run Code Online (Sandbox Code Playgroud)

工人是包含大量观察结果的反射表.我想这样做的原因是像worker.earnings()这样的方法非常慢,因为所有sqlalchemy开销(我的应用程序不需要).例如,如果self.wage是普通班级的财产,那么访问self.wage的速度要慢10倍.

Ant*_*sma 5

如果你需要永久地解除一个类,只需处理映射器:

sqlalchemy.orm.class_mapper(Worker).dispose()
Run Code Online (Sandbox Code Playgroud)

SQLAlchemy检测作为类对象的属性描述符.因此,如果您需要单独的deinstrumented版本的对象,则需要创建一个类的版本,该类在其类型层次结构中没有描述符.

一种好方法是为每个模型类创建一个持久子类,并为持久化类创建映射器.这是一个类装饰器,它为您创建子类并将其作为类属性添加到原始类:

def deinstrumentable(cls):
    """Create a deinstrumentable subclass of the class."""
    def deinstrument(self):
        """Create a non-instrumented copy of the object."""
        obj = cls.__new__(cls)
        obj.__dict__.update(self.__dict__)
        del obj._sa_instance_state
        return obj

    persistent = type('Persisted%s' % cls.__name__, (cls,), {
        'Base': cls,
        'deinstrument': deinstrument
    })

    return persistent
Run Code Online (Sandbox Code Playgroud)

您可以在定义中使用它,如下所示:

@deinstrumentable
class Worker(object):
    def earnings(self):
        return self.wage*self.hours

mapper(Worker, workers)
Run Code Online (Sandbox Code Playgroud)

当你有一个持久对象时,你可以像这样创建一个deinstrumented版本:

worker = session.query(Worker).first()
detached_worker = worker.deinstrument()
Run Code Online (Sandbox Code Playgroud)

您可以像这样直接创建一个detrutrumented版本:

detached_worker = Worker.Base()
Run Code Online (Sandbox Code Playgroud)