Commande SQL de débogage (affichage) envoyée à la base de données par SQLAlchemy

87

J'ai une classe ORM appelée Person, qui s'enroule autour d'une table de personne:

Après avoir configuré la connexion à la base de données, etc., j'exécute l'instruction:

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

La table person ne contient aucune donnée (pour le moment), donc lorsque j'imprime la variable people, j'obtiens une liste vide.

J'ai renommé la table référencée dans ma classe ORM People, to people_foo(qui n'existe pas).

Je relance ensuite le script. J'ai été surpris qu'aucune exception n'ait été lancée lors de la tentative d'accès à une table qui n'existe pas.

J'ai donc les 2 questions suivantes:

  1. Comment puis-je configurer SQLAlchemy pour qu'il propage les erreurs de base de données dans le script?
  2. Comment puis-je afficher (c'est-à-dire imprimer) le SQL qui est envoyé au moteur de base de données?

Si cela aide, j'utilise PostgreSQL.

[Éditer]

J'écris un paquet. Dans mon __main__.pyscript, j'ai le code suivant (raccourci ici):

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

Le module commun configure correctement l'enregistreur et je peux utiliser l'enregistreur dans mes autres modules qui importent du commun.

Cependant, dans le dbfuncsmodule, j'obtiens l'erreur / l'avertissement suivant:

Aucun gestionnaire n'a été trouvé pour le journal "sqlalchemy.engine.base.Engine

morpheous
la source
L'indention du code est cassée, je ne vois aucun common.setup_logger()appel (en supposant qu'il configure correctement la journalisation) ici. De plus, vous n'en avez pas besoin echo=Truelorsque vous utilisez la journalisation.
Denis Otkidach
@denis: Oui, l'enregistreur est correctement configuré dans le module commun - je peux me connecter à d'autres modules. Pour le module dbfuncs.py. J'obtiens l'erreur: aucun gestionnaire n'a pu être trouvé pour l'enregistreur "sqlalchemy.engine.base.Engine
morpheous
1
"Aucun gestionnaire n'a pu être trouvé pour l'enregistreur" signifie que l'enregistreur racine n'a aucun gestionnaire, c'est-à-dire que l'enregistreur n'est pas encore configuré correctement. Vous avez probablement configuré un enregistreur spécifique (et non root) uniquement (et vous pouvez donc l'utiliser) ou vous l'avez configuré après sa première utilisation.
Denis Otkidach

Réponses:

209

En plus du echoparamètre de, create_engine()il existe un moyen plus flexible: la configuration loggingdes instructions du moteur d'écho:

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

Consultez la section Configuration de la journalisation de la documentation pour plus d'informations.

Denis Otkidach
la source
1
@dennis: c'est ce que je préférerais faire - me connecter à un fichier à la place de la console opf. J'utilise déjà la journalisation dans le .py principal de mon package (voir mon code modifié) - après avoir apporté les modifications que vous avez recommandées, maintenant les messages n'apparaissent plus sur la console (bon), mais ils n'apparaissent pas non plus dans le fichier journal (mal). Pourriez-vous clarifier comment enregistrer les messages dans un fichier?
morpheous
3
Existe-t-il un moyen d'ajouter une jolie impression? La façon dont mes requêtes sont générées par défaut est un petit désastre.
rr-
Est-ce donc impossible de se connecter à un fichier à la fin? J'ai fouillé profondément dans la documentation et le débordement de pile, mais personne ne semble se soucier de ce problème, même lorsque la question est clairement posée par quelqu'un comme Morpheous l'a fait ci-dessus. Y a-t-il quelque chose d'évident ici?
Romain Vincent
1
@RomainVincent Il est possible de diriger les informations enregistrées où vous le souhaitez, y compris le fichier, en configurant la journalisation.
Denis Otkidach
78

Vous pouvez voir les instructions SQL envoyées à la base de données en passant echo=Truelors de la création de l'instance de moteur (généralement en utilisant l' appel create_engine()ou engine_from_config()dans votre code).

Par exemple:

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

Par défaut, les instructions journalisées vont à stdout.

Menno Smits
la source