Comando SQL de depuração (exibição) enviado ao banco de dados por SQLAlchemy

87

Eu tenho uma classe ORM chamada Person, que envolve uma tabela de pessoa:

Depois de configurar a conexão com o banco de dados etc., executo a instrução:

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

A tabela pessoa não contém nenhum dado (ainda), então, quando imprimo a variável people, obtenho uma lista vazia.

Mudei o nome da tabela referida em minha classe ORM Peoplepara people_foo(que não existe).

Em seguida, executo o script novamente. Fiquei surpreso que nenhuma exceção foi lançada ao tentar acessar uma tabela que não existe.

Portanto, tenho as seguintes 2 perguntas:

  1. Como posso configurar o SQLAlchemy para que ele propague erros de banco de dados de volta para o script?
  2. Como posso ver (ou seja, imprimir) o SQL que está sendo enviado para o mecanismo db?

Se ajudar, estou usando PostgreSQL.

[Editar]

Estou escrevendo um pacote. Em meu __main__.pyscript, tenho o seguinte código (abreviado aqui):

### __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)

[Edit2]

Módulo comum configura o logger corretamente, e posso usar o logger em meus outros módulos que importam common.

No entanto, no dbfuncsmódulo, estou recebendo o seguinte erro / aviso:

Nenhum manipulador foi encontrado para o logger "sqlalchemy.engine.base.Engine

morfeo
fonte
O recuo do código está quebrado, não vejo nenhuma common.setup_logger()chamada (presumindo que configure o log corretamente) aqui. Além disso, você não precisa echo=Trueao usar o registro.
Denis Otkidach
@denis: Sim, o logger está configurado corretamente no módulo comum - eu consigo fazer login em outros módulos. Para o módulo dbfuncs.py. Recebo o erro: Nenhum manipulador foi encontrado para o logger "sqlalchemy.engine.base.Engine
morpheous de
1
"Nenhum manipulador foi encontrado para o logger" significa que o logger root não tem manipuladores, ou seja, o logger ainda não está configurado corretamente. Provavelmente você configurou algum logger específico (não root) apenas (e, portanto, pode usá-lo) ou configurou-o depois de ser usado pela primeira vez.
Denis Otkidach

Respostas:

209

Além do echoparâmetro de, create_engine()há uma maneira mais flexível: configurando loggingpara ecoar declarações do mecanismo:

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

Consulte a seção Configuração de registro da documentação para obter mais informações.

Denis Otkidach
fonte
1
@dennis: isso é o que eu prefiro fazer - logar no arquivo ao invés do console do opf. Já estou usando o log no principal .py do meu pacote (veja meu código editado) - depois de fazer as alterações que você recomendou, agora as mensagens não estão mais aparecendo no console (bom), mas também não estão aparecendo no arquivo de log (mau). Você poderia esclarecer como fazer com que as mensagens sejam registradas em arquivo?
morfeo de
3
Existe alguma maneira de adicionar uma impressão bonita? A forma como minhas consultas são geradas por padrão é um pequeno desastre.
rr-
Portanto, é impossível fazer login em um arquivo no final? Eu pesquisei profundamente nos documentos e estouro de pilha, mas ninguém parece se importar com esse problema, mesmo quando a pergunta é claramente feita por alguém como Morfeo fez acima. Existe algo óbvio aqui?
Romain Vincent
1
@RomainVincent É possível direcionar as informações registradas para onde você quiser, incluindo arquivos, configurando o registro.
Denis Otkidach de
78

Você pode ver as instruções SQL sendo enviadas para o banco de dados, passando echo=Truequando a instância do mecanismo é criada (geralmente usando a chamada create_engine()ou engine_from_config()em seu código).

Por exemplo:

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

Por padrão, as declarações registradas vão para stdout.

Menno Smits
fonte