SQLAlchemy, obtener objeto no vinculado a una sesión

Por varias razones, estoy tratando de obtener colecciones de objetos de una base de datos y pasarlo a otro proceso que no esté conectado a la base de datos. Mi código se parece al de abajo pero sigo recibiendo

sqlalchemy.exc.UnboundExecutionError: Instance  is not bound to a Session; attribute refresh operation cannot proceed 

Cuando bash ver los elementos de mi lista fuera del método get_list() .

 def get_list (obj): sesson = Session() lst = session.query(MyClass).all() session.close() return lst 

Sin embargo, si uso este

 def get_list_bis (obj) session = Session() return session.query(MyClass).all() 

Puedo usar los elementos pero me preocupa el estado de la sesión ya que no se cerró.

¿Que me estoy perdiendo aqui?

Si desea que un montón de objetos producidos al consultar una sesión se pueda utilizar fuera del scope de la sesión, debe eliminarlos para la sesión.

En su primer ejemplo de función, deberá agregar una línea:

 session.expunge_all() 

antes de

 session.close() 

Más generalmente, digamos que la sesión no se cierra de inmediato, como en el primer ejemplo. Quizás esta es una sesión que se mantiene activa durante toda la duración de una solicitud web o algo así. En tales casos, no desea hacer expunge_all . Usted querrá ser más quirúrgico:

 for item in lst: session.expunge(item) 

Esto sucede a menudo debido a que los objetos están en estado expired , los objetos caducan, por ejemplo, después de la confirmación , luego, cuando dichos objetos caducados están a punto de usarse, el ORM intenta refresh , pero esto no se puede hacer cuando los objetos se separan de la sesión (porque eso la sesión fue, por ejemplo, cerrada ). Este comportamiento se puede gestionar creando una sesión con expire_on_commit=False param.

 >>> from sqlalchemy import inspect >>> insp = inspect(my_object) >>> insp.expired True # then it will be refreshed... 

En mi caso, también estaba guardando una entidad relacionada, y esta receta me ayudó a actualizar todas las instancias dentro de una sesión, aprovechando el hecho de que Session es iterable:

 map(session.refresh, iter(session)) # call refresh() on every instance 

Esto es extremadamente ineficaz, pero funciona. Debería estar bien para pruebas unitarias.

Nota final: en Python3 map() es un generador y no hará nada. Usar bucles reales de listas de comprensión.