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 помещает сеанс в реестр «запросов». При использовании подобных схем идея «создать новый сеанс при запуске запроса» продолжает выглядеть как самый простой способ сохранить ясность.