Depuración (visualización) del comando SQL enviado a la base de datos por SQLAlchemy

87

Tengo una clase ORM llamada Person, que se envuelve alrededor de una tabla de personas:

Después de configurar la conexión a la base de datos, etc., ejecuto la declaración:

people = session.query(Person).all()

La tabla de personas no contiene ningún dato (hasta ahora), así que cuando imprimo la variable people, obtengo una lista vacía.

Cambié el nombre de la tabla a la que se hace referencia en mi clase ORM People, a people_foo(que no existe).

Luego ejecuto el script nuevamente. Me sorprendió que no se lanzara ninguna excepción al intentar acceder a una tabla que no existe.

Por lo tanto, tengo las siguientes 2 preguntas:

  1. ¿Cómo puedo configurar SQLAlchemy para que propague los errores de db al script?
  2. ¿Cómo puedo ver (es decir, imprimir) el SQL que se envía al motor de base de datos?

Si ayuda, estoy usando PostgreSQL.

[Editar]

Estoy escribiendo un paquete. En mi __main__.pyscript, tengo el siguiente código (abreviado aquí):

### __main__.py
import common # imports logging and defines logging setup funcs etc

logger = logging.getLogger(__name__)


def main():    
    parser = OptionParser(usage="%prog [options] <commands>",
                          version="%prog 1.0")

    commands = OptionGroup(parser, "commands")

    parser.add_option(
        "-l",
        "--logfile",
        dest="logfile",
        metavar="FILE",
        help="log to FILE. if not set, no logging will be done"
    )

    parser.add_option(
        "--level",
        dest="loglevel",
        metavar="LOG LEVEL",
        help="Debug level. if not set, level will default to low"
    )

    # Set defaults if not specified
    if not options.loglevel:
        loglevel = 1
    else:
        loglevel = options.loglevel

    if not options.logfile:
        logfilename = 'datafeed.log'
    else:
        logfilename = options.logfile

    common.setup_logger(False, logfilename, loglevel) 

       # and so on ...



        #### dbfuncs.py


import logging

    # not sure how to 'bind' to the logger in __main__.py
    logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)

    engine = create_engine('postgres://postgres:pwd@localhost:port/dbname', echo=True)

[Editar2]

El módulo común configura el registrador correctamente y puedo usar el registrador en mis otros módulos que importan comunes.

Sin embargo, en el dbfuncsmódulo, recibo el siguiente error / advertencia:

No se pudieron encontrar controladores para el registrador "sqlalchemy.engine.base.Engine

morfeo
fuente
La sangría del código está rota, no veo ninguna common.setup_logger()llamada (suponiendo que configure el registro correctamente) aquí. Además, no es necesario echo=Truecuando se utiliza el registro.
Denis Otkidach
@denis: Sí, el registrador está configurado correctamente en el módulo común; puedo iniciar sesión en otros módulos. Para el módulo dbfuncs.py. Recibo el error: No se pudieron encontrar controladores para el registrador "sqlalchemy.engine.base.Engine
morpheous
1
"No se pudieron encontrar controladores para el registrador" significa que el registrador raíz no tiene controladores, es decir, el registrador aún no está configurado correctamente. Probablemente haya configurado solo algún registrador específico (no root) (y para que pueda usarlo) o lo haya configurado después de usarlo por primera vez.
Denis Otkidach

Respuestas:

209

Además del echoparámetro de create_engine()hay una forma más flexible: configurar loggingpara hacer eco de las declaraciones del motor:

import logging
logging.basicConfig()
logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)

Consulte la sección Configuración de registro de la documentación para obtener más información.

Denis Otkidach
fuente
1
@dennis: esto es lo que preferiría hacer: iniciar sesión en el archivo en lugar de la consola opf. Ya estoy usando el registro en el .py principal de mi paquete (ver mi código editado); después de realizar los cambios que recomendó, ahora los mensajes ya no aparecen en la consola (bueno), pero tampoco aparecen en el archivo de registro (malo). ¿Podría aclarar cómo hacer que los mensajes se registren en el archivo?
morpheous
3
¿Hay alguna forma de agregar una impresión bonita? La forma en que mis consultas se generan de forma predeterminada es un pequeño desastre.
rr-
Entonces, ¿es imposible iniciar sesión en un archivo al final? He buscado profundamente en los documentos y el desbordamiento de la pila, pero a nadie parece importarle este problema, incluso cuando alguien como morpheous hizo la pregunta claramente. ¿Hay algo obvio aquí?
Romain Vincent
1
@RomainVincent Es posible dirigir la información registrada a donde quiera, incluido el archivo, configurando el registro.
Denis Otkidach
78

Puede ver las sentencias SQL que se envían a la base de datos pasando echo=Truecuando se crea la instancia del motor (generalmente usando la llamada create_engine()o engine_from_config()en su código).

Por ejemplo:

engine = sqlalchemy.create_engine('postgres://foo/bar', echo=True)

De forma predeterminada, las declaraciones registradas van a stdout.

Menno Smits
fuente