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

标签 python optimization sqlalchemy

是否有一种简单的方法可以“取消检测”来自 sqlalchemy 的 ORM 的实例化类,即将其转换为常规对象?

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

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

mapper(Worker,workers)

其中 workers 是一个包含大量观察结果的反射表。我想这样做的原因是像 worker.earnings() 这样的方法非常慢,因为所有的 sqlalchemy 开销(我的应用程序不需要)。例如,访问 self.wage 比 self.wage 是普通类的属性慢 10 倍左右。

最佳答案

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

sqlalchemy.orm.class_mapper(Worker).dispose()

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

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

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

你可以像这样在定义中使用它:

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

mapper(Worker, workers)

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

worker = session.query(Worker).first()
detached_worker = worker.deinstrument()

你可以像这样直接创建一个deinstrumented版本:

detached_worker = Worker.Base()

关于python - "De-instrument"来自 sqlalchemy ORM 的实例化对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2249694/

相关文章:

python - numpy中的随机单热矩阵

python - 在Python中使用HTMLParser解析html中的特定链接?

python - 如何让这个过程更快?

算法优化 : loop to find pair of items in 3D space

python - SQLAlchemy - WHERE 子句中的子查询

python - 我如何使用 Psycopg2 的 LoggingConnection?

python - mpmath 函数 hyperu 的默认精度是多少?

algorithm - 最小化有向图中树路径的成本

python - 如何在 SQLAlchemy for PostgreSQL 中设置事务隔离级别?

sqlalchemy - 使用 Jupyter SQL Magic 时如何关闭连接?