¿Cómo guardar los valores de traceback / sys.exc_info () en una variable?

Quiero guardar el nombre del error y los detalles de rastreo en una variable. Aquí está mi bash.

import sys try: try: print x except Exception, ex: raise NameError except Exception, er: print "0", sys.exc_info()[0] print "1", sys.exc_info()[1] print "2", sys.exc_info()[2] 

Salida:

 0  1 2  

Salida deseada:

 0 NameError 1 2 Traceback (most recent call last): File "exception.py", line 6, in  raise NameError 

PD: Sé que esto se puede hacer fácilmente usando el módulo de rastreo, pero quiero saber el uso del objeto sys.exc_info () [2] aquí.

Así es como lo hago:

 >>> import traceback >>> try: ... int('k') ... except: ... var = traceback.format_exc() ... >>> print var Traceback (most recent call last): File "", line 2, in  ValueError: invalid literal for int() with base 10: 'k' 

Sin embargo, debe consultar la documentación de rastreo , ya que puede encontrar métodos más adecuados, dependiendo de cómo quiera procesar su variable después …

sys.exc_info () devuelve una tupla con tres valores (tipo, valor, rastreo).

  1. Aquí el tipo obtiene el tipo de excepción de la excepción que se está manejando.
  2. valor son los argumentos que se pasan al constructor de la clase de excepción
  3. el rastreo contiene la información de la stack, como dónde ocurrió la excepción, etc.

Por ejemplo, en el siguiente progtwig

 try: a = 1/0 except Exception,e: exc_tuple = sys.exc_info() 

Ahora si imprimimos la tupla los valores serán los siguientes.

  1. el valor de exc_tuple [0] será ” ZeroDivisionError
  2. exc_tuple [1] valor será ” división entera o módulo por cero ” (Cadena pasada como parámetro a la clase de excepción)
  3. exc_tuple [2] el valor será ” objeto de trackback en (dirección de memoria)

Los detalles anteriores también se pueden recuperar simplemente imprimiendo la excepción en formato de cadena.

 print str(e) 

Use traceback.extract_stack() si desea un acceso conveniente a los nombres de funciones y módulos y los números de línea.

Use ''.join(traceback.format_stack()) si solo quiere una cadena que se parece a la salida de traceback.print_stack() .

Tenga en cuenta que incluso con ''.join() obtendrá una cadena multilínea, ya que los elementos de format_stack() contienen \n . Vea la salida a continuación.

Recuerda import traceback .

Aquí está la salida de traceback.extract_stack() . Formato añadido para facilitar la lectura.

 >>> traceback.extract_stack() [ ('', 1, '', None), ('C:\\Python\\lib\\idlelib\\run.py', 126, 'main', 'ret = method(*args, **kwargs)'), ('C:\\Python\\lib\\idlelib\\run.py', 353, 'runcode', 'exec(code, self.locals)'), ('', 1, '', None) ] 

Aquí está la salida de ''.join(traceback.format_stack()) . Formato añadido para facilitar la lectura.

 >>> ''.join(traceback.format_stack()) ' File "", line 1, in \n File "C:\\Python\\lib\\idlelib\\run.py", line 126, in main\n ret = method(*args, **kwargs)\n File "C:\\Python\\lib\\idlelib\\run.py", line 353, in runcode\n exec(code, self.locals)\n File "", line 1, in \n' 

Tenga cuidado cuando saque el objeto de excepción o el objeto de rastreo del controlador de excepciones, ya que esto causa referencias circulares y gc.collect() no podrá recostackr. Esto parece ser un problema particular en el entorno del portátil ipython / jupyter donde el objeto de rastreo no se borra en el momento correcto e incluso una llamada explícita a gc.collect() en la sección finally no hace nada. Y ese es un gran problema si tiene algunos objetos enormes que no pueden recuperar su memoria debido a eso (por ejemplo, las excepciones de memoria de CUDA que no tienen esta solución requieren un reinicio completo del kernel para recuperarse).

En general, si desea guardar el objeto de rastreo, debe borrarlo de las referencias a locals() , así:

 import sys, traceback, gc type, val, tb = None, None, None try: myfunc() except: type, val, tb = sys.exc_info() traceback.clear_frames(tb) # some cleanup code gc.collect() # and then use the tb: if tb: raise type(val).with_traceback(tb) 

En el caso de la notebook jupyter, debe hacerlo al menos dentro del controlador de excepciones:

 try: myfunc() except: type, val, tb = sys.exc_info() traceback.clear_frames(tb) raise type(val).with_traceback(tb) finally: # cleanup code in here gc.collect() 

Probado con python 3.7.

ps, el problema con ipython o jupyter notebook env es que tiene %tb magic que guarda el rastreo y lo pone a disposición en cualquier momento. Y como resultado, cualquier locals() en todos los cuadros que participan en el rastreo no se liberará hasta que el portátil salga u otra excepción sobrescriba el rastreo almacenado anteriormente. Esto es muy problemático. No debe almacenar el rastro sin limpiar sus marcos. Arreglo enviado aquí .

El objeto se puede usar como un parámetro en la función Exception.with_traceback() :

 except Exception as e: tb = sys.exc_info() print(e.with_traceback(tb[2]))