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