SQLAlchemy DetachedInstanceError с регулярным атрибутом (не отношение)

Я только что начал использовать SQLAlchemy, и получите DetachedInstanceError, и не может найти много информации об этом нигде. Я использую экземпляр вне сессии, таким образом, естественно, что SQLAlchemy не может загрузить любые отношения, если они уже не загружаются, однако, атрибут, к которому я получаю доступ, не является отношением, на самом деле этот объект не имеет никаких отношений вообще. Я нашел решения, такие как нетерпеливая загрузка, но я не могу обратиться к этому, потому что это не отношение. Я даже пытался "коснуться" этого атрибута прежде, чем закрыть сеанс, но он все еще не предотвращает исключение. Что могло вызывать это исключение для нереляционного свойства даже после того, как к нему успешно получили доступ однажды? Любая справка в отладке этой проблемы ценится. Я между тем попытаюсь получить восстанавливаемый автономный сценарий и обновление здесь.

Обновление: Это - фактическое сообщение об исключении с несколькими стеками:

  File "/home/hari/bin/lib/python2.6/site-packages/SQLAlchemy-0.6.1-py2.6.egg/sqlalchemy/orm/attributes.py", line 159, in __get__
    return self.impl.get(instance_state(instance), instance_dict(instance))
  File "/home/hari/bin/lib/python2.6/site-packages/SQLAlchemy-0.6.1-py2.6.egg/sqlalchemy/orm/attributes.py", line 377, in get
    value = callable_(passive=passive)
  File "/home/hari/bin/lib/python2.6/site-packages/SQLAlchemy-0.6.1-py2.6.egg/sqlalchemy/orm/state.py", line 280, in __call__
    self.manager.deferred_scalar_loader(self, toload)
  File "/home/hari/bin/lib/python2.6/site-packages/SQLAlchemy-0.6.1-py2.6.egg/sqlalchemy/orm/mapper.py", line 2323, in _load_scalar_attributes
    (state_str(state)))
DetachedInstanceError: Instance <ReportingJob at 0xa41cd8c> is not bound to a Session; attribute refresh operation cannot proceed

Частичная модель похожа на это:

metadata = MetaData()
ModelBase = declarative_base(metadata=metadata)

class ReportingJob(ModelBase):
    __tablename__ = 'reporting_job'

    job_id         = Column(BigInteger, Sequence('job_id_sequence'), primary_key=True)
    client_id      = Column(BigInteger, nullable=True)

И поле client_id - то, что вызывает это исключение с использованием как ниже:

Запрос:

    jobs = session \
            .query(ReportingJob) \
            .filter(ReportingJob.job_id == job_id) \
            .all()
    if jobs:
        # FIXME(Hari): Workaround for the attribute getting lazy-loaded.
        jobs[0].client_id
        return jobs[0]

Это - то, что инициировало исключение позже из объема сессии:

        msg = msg + ", client_id: %s" % job.client_id
44
задан haridsv 14 June 2010 в 18:17
поделиться

1 ответ

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

  • Оставить сеанс открытым (что очевидно)
  • Укажите expire_on_commit = False для sessionmaker () .

Третий вариант - вручную установить для expire_on_commit значение False в сеансе после его создания, например: session.expire_on_commit = False . Я убедился, что это решает мою проблему.

60
ответ дан 26 November 2019 в 22:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: