¿Cómo puedo modificar un objeto de rastreo de Python al generar una excepción?

StackOverflow https://stackoverflow.com/questions/1603940

  •  05-07-2019
  •  | 
  •  

Pregunta

Estoy trabajando en una biblioteca de Python utilizada por desarrolladores externos para escribir extensiones para nuestra aplicación principal.

Me gustaría saber si es posible modificar el rastreo al generar excepciones, por lo que el último marco de pila es la llamada a la función de biblioteca en el código del desarrollador, en lugar de la línea en la biblioteca que generó la excepción. También hay algunos marcos en la parte inferior de la pila que contienen referencias a las funciones utilizadas al cargar por primera vez el código que, idealmente, me gustaría eliminar también.

Gracias de antemano por cualquier consejo!

¿Fue útil?

Solución

¿Qué hay de no cambiar el rastreo? Las dos cosas que solicita se pueden hacer con mayor facilidad de una manera diferente.

  1. Si la excepción de la biblioteca está atrapada en el código del desarrollador y en su lugar se lanza una nueva excepción, el rastreo original se lanzará, por supuesto. Así es como generalmente se manejan las excepciones ... si solo permite que se genere la excepción original, pero la munge para eliminar todas las " superior " marcos, la excepción real no tendrá sentido, ya que la última línea en el rastreo no sería capaz de generar la excepción.
  2. Para eliminar los últimos marcos, puede solicitar que sus tracebacks se acorten ... cosas como traceback.print_exception () toman un " límite " parámetro que puede usar para omitir las últimas entradas.

Dicho esto, debería ser bastante posible munge the tracebacks si realmente necesitas ... pero ¿dónde lo harías? Si en algún código de envoltorio en el nivel más alto, simplemente puede agarrar el rastreo, tomar un trozo para eliminar las partes que no desea, y luego usar las funciones en el " rastreo del " Módulo para formatear / imprimir como se desee.

Otros consejos

Puedes eliminar la parte superior del rastreo fácilmente subiendo con el elemento tb_next del rastreo:

except:
    ei = sys.exc_info()
    raise ei[0], ei[1], ei[2].tb_next

tb_next es un atributo read_only, por lo que no conozco una manera de eliminar cosas de la parte inferior. Es posible que pueda alterar el mecanismo de propiedades para permitir el acceso a la propiedad, pero no sé cómo hacerlo.

Eche un vistazo a lo que hace jinja2 aquí:

También te puede interesar PEP-3134 , que está implementado en Python 3 y le permite agregar una excepción / rastreo a una excepción en sentido ascendente.

Esto no es exactamente lo mismo que modificar el rastreo, pero probablemente sería la forma ideal de transmitir la " versión corta " a los usuarios de la biblioteca mientras aún tienen la versión " versión larga " disponible.

Este código podría interesarte.

Toma un rastreo y elimina el primer archivo, que no debería mostrarse. Luego simula el comportamiento de Python:

Traceback (most recent call last):

solo se mostrará si el rastreo contiene más de un archivo. Esto parece exactamente como si mi marco adicional no estuviera allí.

Aquí está mi código, asumiendo que hay una cadena text :

try:
    exec(text)
except:
    # we want to format the exception as if no frame was on top.
    exp, val, tb = sys.exc_info()
    listing = traceback.format_exception(exp, val, tb)
    # remove the entry for the first frame
    del listing[1]
    files = [line for line in listing if line.startswith("  File")]
    if len(files) == 1:
        # only one file, remove the header.
        del listing[0]
    print("".join(listing), file=sys.stderr)
    sys.exit(1)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top