Python SQLAlchemy中可变numpy数组的历史记录中没有旧值

Python SQLAlchemy中可变numpy数组的历史记录中没有旧值,python,numpy,sqlalchemy,mutable,Python,Numpy,Sqlalchemy,Mutable,我正在尝试编写存储在数据库中的numpy数组的版本历史记录。每次编辑数组并将其提交到数据库时,我都希望将以前未编辑的数组版本保存在单独的表中。我将numpy数组存储在PickleType列中,并使用可变mixin编写了一个包装类来检测对数组的更改 使用我编写的MutableNumpy类,我可以检测数组的更改(即,行显示在会话.dirty中,更新的值显示在检查(行).attrs.data.history.added)。但是,我在访问阵列的原始未修改版本时遇到问题,我需要为版本历史记录捕获该版本。其

我正在尝试编写存储在数据库中的numpy数组的版本历史记录。每次编辑数组并将其提交到数据库时,我都希望将以前未编辑的数组版本保存在单独的表中。我将numpy数组存储在PickleType列中,并使用可变mixin编写了一个包装类来检测对数组的更改

使用我编写的MutableNumpy类,我可以检测数组的更改(即,行显示在
会话.dirty
中,更新的值显示在
检查(行).attrs.data.history.added
)。但是,我在访问阵列的原始未修改版本时遇到问题,我需要为版本历史记录捕获该版本。其他问题,如建议原始值应显示在历史记录的
deleted
部分,的示例似乎也使用
get_history
deleted
属性访问旧值

我已经探索了使用
active\u history=True
for,但这还没有取得成果。我还检查了
session.rollback()
是否恢复了未编辑的数组,因此我知道未编辑的数组在某处可用

下面是一个最简单的工作示例,使用MutableNumpy包装类、一个简单的表定义和一些数据库操作来说明这个问题

import numpy as np
from sqlalchemy import Column, Integer
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.mutable import Mutable
from sqlalchemy.types import PickleType


Base = declarative_base()

class MutableNumpy(Mutable, np.ndarray):
    @classmethod
    def coerce(cls, key, value):
        "Convert plain numpy arrays to MutableNumpy."
        if not isinstance(value, MutableNumpy):
            if isinstance(value, np.ndarray):
                mutable_array = MutableNumpy(shape=value.shape, dtype=value.dtype, buffer=value)
                return mutable_array

            # this call will raise ValueError
            return Mutable.coerce(key, value)
        else:
            return value

    def __setitem__(self, key, value):
        "Detect array set events and emit change events."
        np.ndarray.__setitem__(self, key, value)
        self.changed()

    def __delitem__(self, key):
        "Detect array del events and emit change events."
        np.ndarray.__delitem__(self, key)
        self.changed()

    def __getstate__(self):
        d = self.__dict__.copy()
        d.pop('_parents', None)
        return d

class MyTable(Base):
    __tablename__ = 'my_table'
    id = Column(Integer, primary_key=True)
    data = Column(MutableNumpy.as_mutable(PickleType))

from sqlalchemy import inspect
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine

engine = create_engine('sqlite:///tmp.db', echo=True)
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
sess = Session()

row = MyTable(data=np.zeros((2, 2), dtype=int))
sess.add(row)
sess.commit()

row.data[0,0] = 1
hist = inspect(row).attrs.data.history
print(hist.added)  # Shows [[1, 0], [0, 0]] as expected
print(hist.unchanged)  # Empty as expected
print(hist.deleted)  # Does NOT show the original array [[0, 0], [0, 0]]