sessionmaker()é uma fábrica, ela existe para encorajar a colocação de opções de configuração para a criação de novos Sessionobjetos em apenas um lugar. É opcional, pois você poderia facilmente chamar a Session(bind=engine, expire_on_commit=False)qualquer momento que precisasse de um novo Session, exceto que é prolixo e redundante, e eu queria impedir a proliferação de "ajudantes" em pequena escala, cada um abordando a questão dessa redundância em algum novo e de forma mais confusa.
Portanto, sessionmaker()é apenas uma ferramenta para ajudá-lo a criar Sessionobjetos quando você precisar deles.
Próxima parte. Acho que a questão é: qual é a diferença entre fazer um novo Session()em vários pontos e apenas usar um até o fim. A resposta, não muito. Sessioné um contêiner para todos os objetos que você coloca nele e também mantém o controle de uma transação aberta. No momento em que você chama rollback()ou commit(), a transação termina e o Sessionnão tem conexão com o banco de dados até que seja chamado para emitir SQL novamente. Os links que ele mantém para seus objetos mapeados são referências fracas, desde que os objetos não tenham alterações pendentes, então, mesmo a esse respeito, o Sessionirá esvaziar-se de volta para um novo estado quando seu aplicativo perder todas as referências aos objetos mapeados. Se você deixar com o padrão"expire_on_commit"configuração, todos os objetos expiram após uma confirmação. Se isso Sessiondurar cinco ou vinte minutos e todos os tipos de coisas mudarem no banco de dados na próxima vez que você usá-lo, ele carregará todos os novos estados da próxima vez que você acessar esses objetos, mesmo que eles estejam na memória por vinte minutos.
Em aplicativos da web, costumamos dizer, ei, por que você não faz um novo Sessionem cada solicitação, em vez de usar o mesmo uma e outra vez. Essa prática garante que a nova solicitação comece "limpa". Se alguns objetos da solicitação anterior ainda não foram coletados como lixo e se talvez você tenha desligado "expire_on_commit", talvez algum estado da solicitação anterior ainda esteja por aí, e esse estado pode até ser bem antigo. Se você tiver o cuidado de deixar expire_on_commitligado e ligar definitivamente commit()ou rollback()no final da solicitação, tudo bem, mas se você começar com um novo Session, então não há dúvida de que você está começando limpo. Portanto, a ideia de iniciar cada solicitação com um novoSessioné realmente apenas a maneira mais simples de ter certeza de que você está começando do zero e de tornar o uso de expire_on_commitpraticamente opcional, já que esse sinalizador pode incorrer em muito SQL extra para uma operação que chama commit()no meio de uma série de operações. Não tenho certeza se isso responde à sua pergunta.
A próxima rodada é o que você menciona sobre threading. Se seu aplicativo for multithread, recomendamos certificar-se de que o Sessionem uso é local para ... algo. scoped_session()por padrão, torna-o local para o segmento atual. Em um aplicativo da web, o local da solicitação é, na verdade, ainda melhor. Na verdade, o Flask-SQLAlchemy envia uma "função de escopo" personalizada scoped_session()para que você obtenha uma sessão com escopo de solicitação. O aplicativo Pyramid médio coloca a Sessão no registro de "solicitação". Ao usar esquemas como esses, a ideia "criar uma nova sessão mediante solicitação inicial" continua a parecer a maneira mais direta de manter as coisas em ordem.