[Python-es] Pyramid + SQLAlchemy + commit() inoportuno

Miguel Sanchez msanchez en uninet.edu
Dom Oct 9 07:50:56 EDT 2022


Hola Lista.

Estoy comenzando con Pyramid + SQLAlchemy y me he atascado.

Es posible que esté haciendo varias cosas mal al mismo tiempo. Les digo cómo lo estoy haciendo:

He definido los modelos, según la documentación recomienda (creo):

class Mitabla(Base):
    __tablename__ = 'mitabla'
    id = Column(Integer, primary_key=True)
    dato1 = Column(Integer)

    def __init__(self, dato1):
        self.dato1 = dato1

    def __setattr__(self, attr, valor):
        if attr == 'dato1':
            if not isinstance(int(valor), int):
                raise ValueError('dato1 no es un int')
        super().__setattr__(attr, valor)


Como pueden ver uso __setattr__ para filtrar los valores que se pueden asignar a las columnas.

He definido una "vista" que va a ser invocada desde un ajax y que espero me devuelva unos valores json:

@view_config(route_name='haceralgo',
             http_cache=0,
             renderer='json'
             )
def haceralgo(request):

En dicha vista tengo varios executes a la sesion del request (request.dbsession)
Unos seleccionan datos, otras borran, otras actualizan

Esto funciona perfectamente, genero una respuesta json y los datos quedan modificados/borrados

try:
    sentencia = select( ....
    resultado = request.dbsession.execute(sentencia).scalar_one()
    sentencia = delete( ....
    request.dbsession.execute(sentencia)
    sentencia = select( ...
    resultado2 = request.dbsession.execute(sentencia).scalar_one()
    resultado2.dato1 = 100

    return Response(.....
except ....

El problema aparece cuando hay un error y quiero capturarlo .... por ejemplo  haciendo que resultado2.dato1 = 'No sea un entero' o simplemente metiendo un 1/0 en el try ... except

Mi idea es capturar el error, loguearlo y enviar un json informando del error

Si hago:
except Exception as error:
    request.dbsession.rollback()
    log.debug(error)
    raise

Todo funciona como debería salvo que no respondo a la petición ajax, lo que llega es un error generado por el servidor:
Internal Server Error
The server encountered an unexpected internal server error
(generated by waitress)


Si hago 
except Exception as error:
    log.debug(error)
    return Response(json.dumps('Datos con el error'),
                    content_type='application/json; charset=utf-8',
                    status=500)
Se genera la respuesta json correctamente
PERO también se genera un commit() que hace que todas las sentencias del try: donde NO se han generado errores (del tipo que sea) se graben en la base de datos
Esto es un problema pues la bd se me queda en un estado inconsistente


Si hago 
except Exception as error:
    request.dbsession.rollback()
    log.debug(error)
    return Response(json.dumps('Datos con el error'),
                    content_type='application/json; charset=utf-8',
                    status=500)

En el servidor se lanza un error: sqlalchemy.exc.ResourceClosedError: This transaction is closed
No se genera la respuesta json
Y llega el mismo error de antes generado por el servidor
Internal Server Error
The server encountered an unexpected internal server error
(generated by waitress)




Alguna sugerencia???, que hago mal???


Gracias y saludos


Miguel Sánchez

























Más información sobre la lista de distribución Python-es