sessionmaker()
- это фабрика, она предназначена для поощрения размещения параметров конфигурации для создания новых Session
объектов в одном месте. Это необязательно, так как вы можете так же легко позвонить в Session(bind=engine, expire_on_commit=False)
любое время, когда вам понадобится новый Session
, за исключением того, что он многословен и избыточен, и я хотел остановить распространение небольших "помощников", каждый из которых подходил к проблеме этой избыточности в каком-то новом и более запутанный способ.
Так sessionmaker()
это просто инструмент , чтобы помочь вам создать Session
объекты , когда вы нуждаетесь в них.
Следующая часть. Я думаю, что вопрос в том, в чем разница между созданием нового Session()
на разных этапах и постоянным использованием одного. Ответ: не очень. Session
является контейнером для всех объектов, которые вы в него помещаете, а также отслеживает открытую транзакцию. В тот момент, когда вы вызываете rollback()
или commit()
, транзакция завершена, и у Session
него нет связи с базой данных, пока он не будет вызван для повторной генерации SQL. Связи, которые он держит с вашими сопоставленными объектами, являются слабыми ссылками, при условии, что объекты не содержат ожидающих изменений, поэтому даже в этом отношении Session
он опустошит себя обратно до совершенно нового состояния, когда ваше приложение потеряет все ссылки на сопоставленные объекты. Если вы оставите значение по умолчанию"expire_on_commit"
установки, то все объекты истекли после фиксации. Если это будет Session
длиться пять или двадцать минут, и при следующем использовании в базе данных изменились все виды вещей, при следующем обращении к этим объектам будет загружено все новое состояние, даже если они находились в памяти. в течение двадцати минут.
В веб-приложениях мы обычно говорим: «Эй, почему бы вам не создать новый Session
для каждого запроса, а не использовать один и тот же снова и снова». Такая практика гарантирует, что новый запрос начинается «чистым». Если некоторые объекты из предыдущего запроса еще не были собраны мусором и, возможно, вы отключили его "expire_on_commit"
, возможно, какое-то состояние из предыдущего запроса все еще существует, и это состояние может быть даже довольно старым. Если вы осторожно оставляете expire_on_commit
включенным и обязательно звоните commit()
или rollback()
в конце запроса, тогда все в порядке, но если вы начнете с совершенно нового Session
, тогда нет даже никаких сомнений в том, что вы начинаете чистую. Итак, идея начинать каждый запрос с новогоSession
на самом деле это самый простой способ убедиться, что вы начинаете с нуля, и сделать использование expire_on_commit
практически необязательным, так как этот флаг может повлечь за собой много дополнительных SQL для операции, которая вызывается commit()
в середине серии операций. Не уверен, что это ответ на ваш вопрос.
Следующий раунд - это то, что вы упомянули о многопоточности. Если ваше приложение многопоточное, мы рекомендуем убедиться, что Session
используется локально для ... чего-то. scoped_session()
по умолчанию делает его локальным для текущего потока. На самом деле в веб-приложении даже лучше локально для запроса. Flask-SQLAlchemy фактически отправляет настраиваемую «функцию области видимости», чтобы scoped_session()
вы получали сеанс с областью действия запроса. Среднее приложение Pyramid помещает сеанс в реестр «запросов». При использовании подобных схем идея «создать новый сеанс при запуске запроса» продолжает выглядеть как самый простой способ сохранить ясность.
В дополнение к отличному ответу zzzeek, вот простой рецепт быстрого создания одноразовых, замкнутых сеансов:
Использование:
источник