J'essaie d'apprendre comment fonctionne une application. Et pour cela, j'insère des commandes de débogage comme première ligne du corps de chaque fonction dans le but de consigner le nom de la fonction ainsi que le numéro de ligne (dans le code) où j'envoie un message à la sortie du journal. Enfin, puisque cette application comprend de nombreux fichiers, je souhaite créer un seul fichier journal afin de mieux comprendre le flux de contrôle de l'application.
Voici ce que je sais:
pour obtenir le nom de la fonction, je peux utiliser
function_name.__name__
mais je ne veux pas utiliser le nom_fonction (afin que je puisse rapidement copier et coller un génériqueLog.info("Message")
dans le corps de toutes les fonctions). Je sais que cela pourrait être fait en C en utilisant une__func__
macro, mais je ne suis pas sûr de python.pour obtenir le nom de fichier et le numéro de ligne, j'ai vu que (et je crois que) mon application utilise la
locals()
fonction Python mais dans une syntaxe dont je ne suis pas complètement conscient, par exemple:options = "LOG.debug('%(flag)s : %(flag_get)s' % locals())
et je l'ai essayé en utilisant likeLOG.info("My message %s" % locals())
qui produit quelque chose comme{'self': <__main__.Class_name object at 0x22f8cd0>}
. Des commentaires à ce sujet s'il vous plaît?Je sais comment utiliser la journalisation et y ajouter un gestionnaire pour me connecter à un fichier, mais je ne suis pas sûr qu'un seul fichier puisse être utilisé pour enregistrer tous les messages de journal dans l'ordre correct des appels de fonction dans le projet.
J'apprécierais grandement toute aide.
Merci!
import pdb; pdb.set_trace()
, puis parcourir le code de manière interactive. Cela peut vous aider à suivre le déroulement du programme.Réponses:
Vous avez ici quelques questions marginales.
Je vais commencer par le plus simple: (3). En utilisant,
logging
vous pouvez regrouper tous les appels vers un seul fichier journal ou une autre cible de sortie: ils seront dans l'ordre dans lequel ils se sont produits dans le processus.Ensuite: (2).
locals()
fournit un dict de la portée actuelle. Ainsi, dans une méthode qui n'a pas d'autres arguments, vous avezself
dans la portée, qui contient une référence à l'instance actuelle. L'astuce utilisée qui vous surprend est le formatage de la chaîne en utilisant un dict comme RHS de l'%
opérateur."%(foo)s" % bar
sera remplacé par quelle que soit la valeur debar["foo"]
is.Enfin, vous pouvez utiliser des astuces d'introspection, similaires à celles utilisées par
pdb
qui peuvent enregistrer plus d'informations:Cela enregistrera le message transmis, plus le nom de la fonction (d'origine), le nom de fichier dans lequel la définition apparaît et la ligne dans ce fichier. Jetez un œil à inspect - Inspectez les objets vivants pour plus de détails.
Comme je l'ai mentionné dans mon commentaire plus tôt, vous pouvez également accéder à une
pdb
invite de débogage interactive à tout moment en insérant la ligneimport pdb; pdb.set_trace()
et en réexécutant votre programme. Cela vous permet de parcourir le code en inspectant les données à votre guise.la source
'%(foo)s : %(bar)s'
serait également imprimer labar["foo"]
valeur de s? Ou est-ce quelque peu différent de votre exemple?%(<foo>)s
est remplacé par la valeur de l'objet référencé dans le dict par<foo>
. Il y a plus d'exemples / détails sur docs.python.org/library/stdtypes.html#string-formattingLa bonne réponse pour cela est d'utiliser la
funcName
variable déjà fourniePuis où vous voulez, ajoutez simplement:
Exemple de sortie d'un script sur lequel je travaille en ce moment:
la source
getLogger(__name__)
logging.getLogger('root')
Non pertinent, mais ce n'est probablement pas ce à quoi vous vous attendez, ce n'est pas l'root
enregistreur, mais un enregistreur ordinaire avec le nom «root».funcname
,linename
Etlineno
fournir des informations sur la dernière fonction qui a fait l'enregistrement.Si vous avez un wrapper de logger (par exemple un logger singleton), la réponse de @ synthesizerpatel pourrait ne pas fonctionner pour vous.
Pour connaître les autres appelants dans la pile d'appels, vous pouvez faire:
la source
logging
niveau de soutien de classe à sauter hors de la boîte: méthodes commelog()
,debug()
, etc. acceptent maintenant unstacklevel
argument. Consultez la documentation .