2009-07-08 7 views
9

Exemple:trouver le nom du module de l'exception d'origine en Python

>>> try: 
... myapp.foo.doSomething() 
... except Exception, e: 
... print 'Thrown from:', modname(e) 

Thrown from: myapp.util.url 

Dans l'exemple ci-dessus, l'exception a été effectivement jeté à myapp/util/module url.py. Y at-il un moyen d'obtenir le __name__ de ce module?

Mon intention est d'utiliser ceci dans la fonction logging.getLogger.

Répondre

0

Cela devrait faire l'affaire:

import inspect 
def modname(): 
    t=inspect.trace() 
    if t: 
     return t[-1][1] 
+0

Cela renvoie le module dans lequel l'exception a été * définie *, non? – Stephan202

+0

@ Stephan202: désolé, mal compris la question, la fonction ci-dessus vous donnera le nom du module qui a soulevé l'erreur –

+0

Il renvoie le nom du module ('url'), mais pas la valeur de son __name__' (' myapp. util.url') –

6

Vous pouvez utiliser le traceback module, avec sys.exc_info(), pour obtenir le retraçage programme:

try: 
    myapp.foo.doSomething() 
except Exception, e: 
    exc_type, exc_value, exc_tb = sys.exc_info() 
    filename, line_num, func_name, text = traceback.extract_tb(exc_tb)[-1] 
    print 'Thrown from: %s' % filename 
+0

Le nom de fichier n'est pas le même que' __name__' –

+0

filename + linenumber est plus utile pour moi, alors j'apprécie cette réponse à la question :) – warp

9

Cela devrait fonctionner:

import inspect 

try: 
    some_bad_code() 
except Exception, e: 
    frm = inspect.trace()[-1] 
    mod = inspect.getmodule(frm[0]) 
    print 'Thrown from', mod.__name__ 

EDIT: Stephan202 mentionne un cas de coin. Dans ce cas, je pense que nous pourrions par défaut au nom de fichier.

import inspect 

try: 
    import bad_module 
except Exception, e: 
    frm = inspect.trace()[-1] 
    mod = inspect.getmodule(frm[0]) 
    modname = mod.__name__ if mod else frm[1] 
    print 'Thrown from', modname 

Le problème est que si le module ne se charge pas (parce qu'une exception a été lancée lors de la lecture du code dans ce fichier), puis le retourne appel inspect.getmodule Aucun. Donc, nous utilisons simplement le nom du fichier référencé par le cadre incriminé. (Merci de l'avoir signalé, Stephan202!)

+1

En effet cela fonctionne. Notez qu'il y a un cas d'angle dans lequel il échouera, apparemment (juste essayé): si some_bad_code() est une instruction import qui provoque immédiatement une exception (à cause du code dans le module). – Stephan202

+0

Bon point, Stephan202. J'ai fait un montage qui, je l'espère, répondra de manière adéquate. – ars

+0

@ars J'ai implémenté quelque chose comme ça récemment. Je pense que le fait de ne pas avoir un nom de fichier par défaut ne suffit pas - je regarde en plus dans sys.path et si le nom du fichier est un enfant de l'une des entrées, je le rends relatif. Parfois, cela échoue, car toutes les importations ne proviennent pas de sys.path, mais si cela réussit, je peux supprimer l'extension et remplacer ('\\', '/').replace('/', '.') Et la plupart probablement obtenir le nom du module manquant. –

0

Le package de journalisation de Python prend déjà en charge cette fonctionnalité - vérifiez le documentation. Vous devez simplement spécifier %(module)s dans la chaîne de format. Cependant, cela vous donne le module où l'exception a été pris - pas nécessairement le même que celui où il était soulevé. Le retraçage, bien sûr, vous donne l'emplacement précis où l'exception a été soulevée.

+0

Je veux utiliser '__name__' dans l'argument' logging.getLogger' et non dans la sortie de l'enregistreur. –

+0

Revenons un peu en arrière. Pourquoi est-il si important de l'avoir dans le nom de l'enregistreur?Vous pouvez trouver le fichier exact et le numéro de ligne où l'exception a été lancée, ce qui semble être la chose la plus importante. –

0

J'ai une histoire sur la façon dont CrashKit calcule les noms de classe et les noms de paquets à partir des traces de la pile Python sur le blog de l'entreprise: "Python stack trace saga". Code de travail inclus.

Questions connexes