Comment enregistrer le nom du fichier source et le numéro de ligne en Python

123

Est-il possible de décorer / étendre le système de journalisation standard python, de sorte que lorsqu'une méthode de journalisation est invoquée, elle enregistre également le fichier et le numéro de ligne où elle a été invoquée ou peut-être la méthode qui l'a invoquée?

digy
la source

Réponses:

228

Bien sûr, vérifiez les formateurs dans les documents de journalisation. Plus précisément, les variables lineno et pathname.

% (chemin) s Chemin complet du fichier source où l'appel de journalisation a été émis (si disponible).

% (filename) s Partie du nom de fichier du chemin.

Module% (module) s (partie nom du nom de fichier).

% (funcName) s Nom de la fonction contenant l'appel de journalisation.

% (lineno) d Numéro de la ligne source sur laquelle l'appel de journalisation a été émis (si disponible).

Ressemble à quelque chose comme ceci:

formatter = logging.Formatter('[%(asctime)s] p%(process)s {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s','%m-%d %H:%M:%S')
Seb
la source
1
Et, oui, le désordre majuscules / minuscules dans les variables doit être pris en compte.
Tom Pohl
1
Autrement appelé "cas de chameau très mal mis en œuvre".
Jon Spencer
81

En plus de la réponse très utile de Seb , voici un extrait de code pratique qui montre l'utilisation de l'enregistreur avec un format raisonnable:

#!/usr/bin/env python
import logging

logging.basicConfig(format='%(asctime)s,%(msecs)d %(levelname)-8s [%(filename)s:%(lineno)d] %(message)s',
    datefmt='%Y-%m-%d:%H:%M:%S',
    level=logging.DEBUG)

logger = logging.getLogger(__name__)
logger.debug("This is a debug log")
logger.info("This is an info log")
logger.critical("This is critical")
logger.error("An error occurred")

Génère cette sortie:

2017-06-06:17:07:02,158 DEBUG    [log.py:11] This is a debug log
2017-06-06:17:07:02,158 INFO     [log.py:12] This is an info log
2017-06-06:17:07:02,158 CRITICAL [log.py:13] This is critical
2017-06-06:17:07:02,158 ERROR    [log.py:14] An error occurred
codeforester
la source
5
Utilisez ceci pour plus de détails: formatter = logging.Formatter ('% (asctime) s,% (levelname) -8s [% (filename) s:% (module) s:% (funcName) s:% (lineno) d] % (message) s ')
Girish Gupta
y a-t-il un moyen de changer juste à un endroit en haut du code, que les messages de journalisation soient imprimés ou non? Je voudrais deux modes, un avec beaucoup d'impressions pour voir exactement ce que fait le programme; et un, lorsqu'il est suffisamment stable, où aucune sortie n'est affichée.
Marie. P.
3
@ Marie.P. ne posez pas de questions différentes dans les commentaires. La réponse réside cependant dans les niveaux de journalisation.
bugmenot123
4

Pour construire sur ce qui précède d'une manière qui envoie la journalisation de débogage à la sortie standard:

import logging
import sys

root = logging.getLogger()
root.setLevel(logging.DEBUG)

ch = logging.StreamHandler(sys.stdout)
ch.setLevel(logging.DEBUG)
FORMAT = "[%(filename)s:%(lineno)s - %(funcName)20s() ] %(message)s"
formatter = logging.Formatter(FORMAT)
ch.setFormatter(formatter)
root.addHandler(ch)

logging.debug("I am sent to standard out.")

Mettre ce qui précède dans un fichier appelé debug_logging_example.pyproduit la sortie:

[debug_logging_example.py:14 -             <module>() ] I am sent to standard out.

Ensuite, si vous souhaitez désactiver la déconnexion des commentaires root.setLevel(logging.DEBUG).

Pour les fichiers uniques (par exemple les affectations de classe), j'ai trouvé que c'était une bien meilleure façon de faire cela que d'utiliser des print()instructions. Où il vous permet de désactiver la sortie de débogage en un seul endroit avant de la soumettre.

orangepips
la source
1

Pour les développeurs utilisant PyCharm ou Eclipse pydev, ce qui suit produira un lien vers la source de l'instruction de journal dans la sortie du journal de la console:

import logging, sys, os
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG, format='%(message)s | \'%(name)s:%(lineno)s\'')
log = logging.getLogger(os.path.basename(__file__))


log.debug("hello logging linked to source")

Voir les hyperliens du fichier source Pydev dans la console Eclipse pour une discussion et un historique plus longs.

caractères
la source
0
# your imports above ...


logging.basicConfig(
    format='%(asctime)s,%(msecs)d %(levelname)-8s [%(pathname)s:%(lineno)d in 
    function %(funcName)s] %(message)s',
    datefmt='%Y-%m-%d:%H:%M:%S',
    level=logging.DEBUG
)

logger = logging.getLogger(__name__)

# your classes and methods below ...
# An naive Sample of usage:
try:
    logger.info('Sample of info log')
    # your code here
except Exception as e:
    logger.error(e)

Différente des autres réponses, cela enregistrera le chemin complet du fichier et le nom de la fonction qui aurait pu provoquer une erreur. Ceci est utile si vous avez un projet avec plus d'un module et plusieurs fichiers avec le même nom répartis dans ces modules.

Hosana Gomes
la source