2009-07-08 5 views
9

Ejemplo:Encuentra nombre de módulo de la excepción originario de Python

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

Thrown from: myapp.util.url 

En el ejemplo anterior, la excepción fue en realidad lanzada a miaplicacion/util/módulo url.py. ¿Hay alguna manera de obtener el __name__ de ese módulo?

Mi intención es usar esto en la función logging.getLogger.

Respuesta

0

Esto debe hacer el truco:

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

Devuelve el módulo en el que se definió la excepción *, ¿no? – Stephan202

+0

@ Stephan202: lo siento, he entendido mal la pregunta, la función anterior le dará el nombre del módulo que provocó el error –

+0

Devuelve el nombre del módulo ('url'), pero no el valor de su' __name__' ('myapp. util.url') –

6

Puede utilizar el traceback module, junto con sys.exc_info(), para obtener el rastreo mediante programación:

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

Nombre de archivo no es lo mismo que '__name__' –

+0

nombre de archivo + linenumber es más útil para mí, así que agradezco esta respuesta a la pregunta :) – warp

9

Esto debería funcionar:

import inspect 

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

EDITAR: Stephan202 menciona una caja de esquina. En este caso, creo que podríamos cambiar el nombre del archivo por defecto.

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 

El problema es que si el módulo no recibe carga (debido a una excepción al leer el código en ese archivo), entonces la llamada inspect.getmodule devuelve None. Entonces, solo usamos el nombre del archivo al que hace referencia el marco ofensivo. (Gracias por señalar esto, Stephan202!)

+1

De hecho, esto funciona. Tenga en cuenta que hay un caso de esquina en el que fallará, al parecer (solo intenté): si some_bad_code() es una instrucción de importación que provoca inmediatamente una excepción (debido a algún código en dicho módulo). – Stephan202

+0

Buen punto, Stephan202. Hice una edición, que espero aborde esto adecuadamente. – ars

+0

@ars He estado implementando algo como esto recientemente. Creo que el incumplimiento de un nombre de archivo no es suficiente. También busco a través de sys.path y si el nombre del archivo es un elemento secundario de una de las entradas, lo hago relativo. A veces esto falla, porque no todas las importaciones proceden de sys.path, pero si tiene éxito, puedo eliminar la extensión y reemplazar ('\\', '/').replace('/', '.') Y la mayoría Probablemente obtenga el nombre del módulo que falta. –

0

El paquete de registro de Python ya es compatible con esto - marque el documentation. Solo tiene que especificar %(module)s en la cadena de formato. Sin embargo, esto le proporciona el módulo donde la excepción fue atrapado en - no necesariamente el mismo en el que estaba elevado. El rastreo, por supuesto, le brinda la ubicación precisa donde se presentó la excepción.

+0

Quiero usar '__name__' en el argumento' logging.getLogger' y no en la salida del registrador. –

+0

Retrocedamos un poco. ¿Por qué es tan importante tenerlo en el nombre del registrador?Puede encontrar el archivo exacto y el número de línea donde se lanzó la excepción, que parece ser lo más importante. –

0

Tengo una historia sobre cómo CrashKit calcula nombres de clases y nombres de paquetes de Python stack traces en el blog de la compañía: "Python stack trace saga". Código de trabajo incluido.

Cuestiones relacionadas