Оказывается, что метод по умолчанию redu_ex (я уверен, что это тот, который в object (), но это не обязательно.), Который идет по линии, когда у вас активна sqlalchemy, добавляет член _sa_instance_state
к состоянию, возвращаемому в API redu_ex , который PyYAML использует для выполнения сериализации.
При сериализации объекта, полученного из запроса SqlAlchemy, это по существускрытая часть метаданных объекта, доступная для дальнейших операций.
Именно в этом объекте происходит сбой сериализатора PyYAML.Вы можете убедиться в этом, запустив сериализацию в PDB и увидев два вызова представления_объекта в стеке вызовов, даже для относительно простых результатов объекта запроса SQLAlchemy.
Эта ссылка на экземпляр запроса используется,Насколько я понимаю, использование методов с помощью позволяет вам вернуться к запросу, который генерирует данный объект в течение времени жизни того же интерпретатора Python.
Если вам нужна эта функциональность (например, session.new & session.грязный), вам нужно будет реализовать поддержку для этого в сериализаторе PyYAML.
Если вам все равно, и вы просто хотите, чтобы ваши объявленные члены, вы можете использовать базовый класс, который «скрывает» эту связь от вызовов к уменьшение * - обратите внимание, что это также нарушит расширение сериализатора SQLAlchemy, поэтому внимательно рассмотрите свои планы.
Пример базового класса для реализации этого изменения:
DeclBase = declarative_base()
class Base(DeclBase):
__abstract__ = True
def __reduce_ex__(self, proto):
ret = super(Base, self).__reduce_ex__(proto)
ret = ( ret[0], ret[1], dict(ret[2]) ) + ret[3:]
ret[2].pop('_sa_instance_state', None) # remove bad yamly from reduce state
return ret
Это позволит вам отправлять туда и обратно ваши объекты в / из yaml, хотя и туда и обратноотменит их от любых ожидающих транзакций или запросов.Это также может иметь взаимодействие, если вы используете ленивые загруженные элементы, например.Убедитесь, что вы сериализуете все, что ожидаете.
ПРИМЕЧАНИЕ / РЕДАКТИРОВАТЬ: Я решил использовать здесь redu_ex , чтобы быть совместимым с возможными другими базовыми классами или миксинами.Согласно https://docs.python.org/2/library/pickle.html#object.reduce_ex, это приведет к правильному поведению для любых базовых классов, а также определит, было ли объявлено только lower ().
Redux ... lower возвращает действительное значение dict объекта экземпляра - мы не хотим удалять оттуда, поэтому для __reduce * мы должны фактически сделать мелкую копию этого диктанта.