Как реализовать изменяемые PickleTypes, которые автоматически обновляются при изменении

SQLAlchemy предлагает PickleType и предлагает отслеживание мутаций для любого типа, который изменен (например, dict).

В документации SQLAlchemy упоминается, что это способ реализации изменчивого PickleType но в нем точно не PickleType , как с ним PickleType .

Примечание . Я хочу сохранить dict в PickleType .

Как вы это реализуете?

2 Solutions collect form web for “Как реализовать изменяемые PickleTypes, которые автоматически обновляются при изменении”

Хотя в документации упоминаются некоторые примеры, этого недостаточно для моих глаз, поэтому я добавлю здесь свою реализацию, которая может быть использована для реализации измененного диктата, который маринован и хранится в базе данных.

Используйте пример MutableDict из документов:

 class MutableDict(Mutable, dict): @classmethod def coerce(cls, key, value): if not isinstance(value, MutableDict): if isinstance(value, dict): return MutableDict(value) return Mutable.coerce(key, value) else: return value def __delitem(self, key): dict.__delitem__(self, key) self.changed() def __setitem__(self, key, value): dict.__setitem__(self, key, value) self.changed() def __getstate__(self): return dict(self) def __setstate__(self, state): self.update(self) 

Теперь создайте столбец для отслеживания:

 class MyModel(Base): data = Column(MutableDict.as_mutable(PickleType)) 

Я хотел бы увидеть некоторые другие примеры, которые могут быть более продвинутыми или, возможно, использовать разные структуры данных. Как будет выглядеть общий подход к pickle ? Есть один (я полагаю, нет, или SQLAlchemy бы его).

Вот решение, которое я придумал. Он обертывает любой тип и обнаруживает любые наборы атрибутов и вызовы Mutable.changed (). Он также обертывает вызовы функций и обнаруживает изменения, делая моментальный снимок объекта до и после и сравнивая. Должен работать для типов Pickleable …

 from sqlalchemy.ext.mutable import Mutable class MutableTypeWrapper(Mutable): top_attributes = ['_underlying_object', '_underlying_type', '_last_state', '_snapshot_update', '_snapshot_changed', '_notify_if_changed', 'changed', '__getstate__', '__setstate__', 'coerce'] @classmethod def coerce(cls, key, value): if not isinstance(value, MutableTypeWrapper): try: return MutableTypeWrapper(value) except: return Mutable.coerce(key, value) else: return value def __getstate__(self): return self._underlying_object def __setstate__(self, state): self._underlying_type = type(state) self._underlying_object = state def __init__(self, underlying_object, underlying_type=None): if (underlying_object is None and underlying_type is None): print('Both underlying object and type are none.') raise RuntimeError('Unable to create MutableTypeWrapper with no underlying object or type.') if (underlying_object is not None): self._underlying_object = underlying_object else: self._underlying_object = underlying_type() if (underlying_type is not None): self._underlying_type = underlying_type else: self._underlying_type = type(underlying_object) def __getattr__(self, attr): if (attr in MutableTypeWrapper.top_attributes): return object.__getattribute__(self, attr) orig_attr = self._underlying_object.__getattribute__(attr) if callable(orig_attr): def hooked(*args, **kwargs): self._snapshot_update() result = orig_attr(*args, **kwargs) self._notify_if_changed() # prevent underlying from becoming unwrapped if result == self._underlying_object: return self return result return hooked else: return orig_attr def __setattr__(self, attr, value): if (attr in MutableTypeWrapper.top_attributes): object.__setattr__(self, attr, value) return self._underlying_object.__setattr__(attr, value) self.changed() def _snapshot_update(self): self._last_state = pickle.dumps(self._underlying_object, pickle.HIGHEST_PROTOCOL) def _snapshot_changed(self): return self._last_state != pickle.dumps(self._underlying_object, pickle.HIGHEST_PROTOCOL) def _notify_if_changed(self): if (self._snapshot_changed()): self.changed() 

И затем используйте его с PickleType следующим образом:

 class TestModel(Base): __tablename__ = 'testtable' id = Column(Integer, primary_key=True) obj = Column(MutableTypeWrapper.as_mutable(PickleType)) 

Недостаток здесь заключается в том, что базовый класс моментально снижается перед каждым вызовом функции, а затем изменения сравниваются после того, чтобы проверить, изменился ли базовый объект. Это будет иметь значительное влияние на производительность.

Другой способ убедиться, что ваши объекты PickleType обновляются при их изменении, – это копировать и назначать их перед совершением изменений.

  • Выберите как в sqlalchemy
  • Как получить значения автоинкремента для столбца после загрузки фрейма данных Pandas в базу данных MySQL
  • WTForms QuerySelectMultipleField Не отправляет список
  • Как обновить объект orlChalchemy orm с помощью python dict
  • Как получить месяц и год из поля «Дата» в sqlalchemy?
  • В SQLAlchemy я могу создать Engine из существующего ODBC-соединения?
  • Как найти свойства таблицы из объекта сопоставления SQLAlchemy
  • AttributeError: объект InstrumentedList не имеет атрибута
  • Как моделировать ограничение `UNIQUE` в SQLAlchemy?
  • Целевая база данных не обновляется
  • Как смоделировать отношение «многие ко многим» в трех таблицах в SQLAlchemy (ORM)?
  • Python - лучший язык программирования в мире.