sessionmaker()
es una fábrica, está ahí para fomentar la colocación de opciones de configuración para crear nuevos Session
objetos en un solo lugar. Es opcional, ya que puede llamar con la misma facilidad en Session(bind=engine, expire_on_commit=False)
cualquier momento que necesite un nuevo Session
, excepto que es detallado y redundante, y quería detener la proliferación de "ayudantes" a pequeña escala que abordan el tema de esta redundancia en algún nuevo y forma más confusa.
Entonces sessionmaker()
es solo una herramienta para ayudarlo a crear Session
objetos cuando los necesite.
Parte siguiente. Creo que la pregunta es, ¿cuál es la diferencia entre hacer una nueva Session()
en varios puntos versus simplemente usar una hasta el final? La respuesta, no mucha. Session
es un contenedor para todos los objetos que coloca en él, y luego también realiza un seguimiento de una transacción abierta. En el momento en que llama a rollback()
o commit()
, la transacción ha terminado y Session
no tiene conexión con la base de datos hasta que se le pide que emita SQL nuevamente. Los enlaces que contiene a sus objetos mapeados son referencias débiles, siempre que los objetos estén limpios de cambios pendientes, por lo que incluso en ese sentido, Session
se vaciará a un estado completamente nuevo cuando su aplicación pierda todas las referencias a objetos mapeados. Si lo dejas con su valor predeterminado"expire_on_commit"
, todos los objetos caducan después de una confirmación. Si eso se Session
queda durante cinco o veinte minutos, y todo tipo de cosas han cambiado en la base de datos la próxima vez que la use, se cargará todo el estado nuevo la próxima vez que acceda a esos objetos a pesar de que han estado almacenados en la memoria. durante veinte minutos.
En las aplicaciones web, solemos decir, oye, ¿por qué no haces una nueva Session
en cada solicitud, en lugar de usar la misma una y otra vez? Esta práctica asegura que la nueva solicitud comience "limpia". Si algunos objetos de la solicitud anterior aún no se han recolectado como basura, y si tal vez los desactivó "expire_on_commit"
, tal vez algún estado de la solicitud anterior todavía esté rondando, y ese estado podría incluso ser bastante antiguo. Si tiene cuidado de dejar expire_on_commit
encendido y definitivamente llamar commit()
o rollback()
al final de la solicitud, entonces está bien, pero si comienza con uno nuevo Session
, entonces ni siquiera hay duda de que está comenzando limpio. Entonces, la idea de comenzar cada solicitud con un nuevoSession
es realmente la forma más sencilla de asegurarse de que está comenzando de nuevo y de hacer que el uso sea expire_on_commit
prácticamente opcional, ya que este indicador puede incurrir en una gran cantidad de SQL adicional para una operación que llama commit()
en medio de una serie de operaciones. No estoy seguro de si esto responde a su pregunta.
La siguiente ronda es lo que mencionas sobre el enhebrado. Si su aplicación es multiproceso, le recomendamos que se asegure de que el Session
uso sea local para ... algo. scoped_session()
por defecto lo hace local al hilo actual. En una aplicación web, lo local a la solicitud es incluso mejor. Flask-SQLAlchemy en realidad envía una "función de alcance" personalizada scoped_session()
para que obtenga una sesión de alcance de solicitud. La aplicación Pyramid promedio pega la sesión en el registro de "solicitud". Cuando se utilizan esquemas como estos, la idea de "crear una nueva sesión al inicio de la solicitud" sigue pareciendo la forma más sencilla de mantener las cosas en orden.
Además de la excelente respuesta de zzzeek, aquí hay una receta simple para crear rápidamente sesiones desechables e independientes:
Uso:
fuente