web-dev-qa-db-fra.com

enregistrement avec filtres

J'utilise la journalisation (import logging) Pour enregistrer les messages.

Au sein d'un seul module, j'enregistre des messages au niveau de débogage my_logger.debug('msg');

Certains de ces messages de débogage proviennent de function_a() et d'autres de function_b(); Je voudrais pouvoir activer/désactiver la journalisation selon qu'ils proviennent de a ou de b;

Je suppose que je dois utiliser le mécanisme de filtrage de Logging.

Quelqu'un peut-il me montrer comment le code ci-dessous devrait être instrumenté pour faire ce que je veux?

import logging
logger= logging.getLogger( "module_name" )

def function_a( ... ):
    logger.debug( "a message" )

def function_b( ... ):
    logger.debug( "another message" )

if __name__ == "__main__":
    logging.basicConfig( stream=sys.stderr, level=logging.DEBUG )

    #don't want function_a()'s noise -> ....
    #somehow filter-out function_a's logging
    function_a()

    #don't want function_b()'s noise -> ....
    #somehow filter-out function_b's logging
    function_b()

Si je modifiais cet exemple simple à plus de modules et plus de fonctions par module, je serais préoccupé par beaucoup de loggers;

Puis-je le limiter à 1 enregistreur par module? Notez que les messages du journal sont "structurés", c'est-à-dire que si la ou les fonctions qui le consignent effectuent un travail d'analyse, elles contiennent toutes un préfixe logger.debug("parsing: xxx") - puis-je en quelque sorte avec une seule ligne simplement arrêter tout "analyser" les messages (quel que soit le module/la fonction émettant le message?)

38
jd.

Implémentez simplement une sous-classe de logging.Filter: http://docs.python.org/library/logging.html#filter-objects . Il aura une méthode, filter(record), qui examine l'enregistrement de journal et renvoie True pour le journaliser ou False pour le supprimer. Vous pouvez ensuite installer le filtre sur un Logger ou un Handler en appelant sa méthode addFilter(filter).

Exemple:

class NoParsingFilter(logging.Filter):
    def filter(self, record):
        return not record.getMessage().startswith('parsing')

logger.addFilter(NoParsingFilter())

Ou quelque chose comme ça, de toute façon.

56
David Z

N'utilisez pas global. C'est un accident qui attend de se produire.

Vous pouvez attribuer à vos enregistreurs des noms séparés par des "." Qui sont significatifs pour vous.

Vous pouvez les contrôler comme une hiérarchie. Si vous avez des enregistreurs nommés a.b.c et a.b.d, vous pouvez vérifier le niveau de journalisation pour a.b et modifiez les deux enregistreurs.

Vous pouvez avoir n'importe quel nombre d'enregistreurs - ils sont peu coûteux.

Le modèle de conception le plus courant est un enregistreur par module. Voir Attribution d'un nom Python

Faites ça.

import logging

logger= logging.getLogger( "module_name" )
logger_a = logger.getLogger( "module_name.function_a" )
logger_b = logger.getLogger( "module_name.function_b" )

def function_a( ... ):
    logger_a.debug( "a message" )

def functio_b( ... ):
    logger_b.debug( "another message" )

if __name__ == "__main__":
    logging.basicConfig( stream=sys.stderr, level=logging.DEBUG )
    logger_a.setLevel( logging.DEBUG )
    logger_b.setLevel( logging.WARN )

    ... etc ...
20
S.Lott

J'ai trouvé un moyen plus simple d'utiliser les fonctions de votre script principal:

# rm 2to3 messages
def filter_grammar_messages(record):
    if record.funcName == 'load_grammar':
        return False
    return True

def filter_import_messages(record):
    if record.funcName == 'init' and record.msg.startswith('Importing '):
        return False
    return True

logging.getLogger().addFilter(filter_grammar_messages)  # root
logging.getLogger('PIL.Image').addFilter(filter_import_messages)
1
Gringo Suave