seguimiento reconocimiento raspberry por objetos imagenes forma deteccion contornos con color caracteres python debugging exception-handling

python - reconocimiento - seguimiento y deteccion de objetos por color y forma con opencv



Extraer información de seguimiento de un objeto de excepción (4)

Dado un objeto Exception (de origen desconocido) ¿hay forma de obtener su traceback? Tengo un código como este:

def stuff(): try: ..... return useful except Exception as e: return e result = stuff() if isinstance(result, Exception): result.traceback <-- How?

¿Cómo puedo extraer el rastreo desde el objeto Exception una vez que lo tengo?


Desde Python 3.0 [PEP 3109], la clase incorporada Exception tiene un atributo __traceback__ que contiene un traceback object (con Python 3.2.3):

>>> try: ... raise Exception() ... except Exception as e: ... tb = e.__traceback__ ... >>> tb <traceback object at 0x00000000022A9208>

El problema es que después de __traceback__ Google __traceback__ por un tiempo encontré pocos artículos, pero ninguno de ellos describe si o por qué debería (no) usar __traceback__ .

Sin embargo, la documentación de Python 3 para raise dice que:

Un objeto de rastreo normalmente se crea automáticamente cuando se genera una excepción y se le asocia como atributo __traceback__ , que se puede escribir.

Entonces supongo que debe ser usado.


Hay una muy buena razón por la que el rastreo no se almacena en la excepción; debido a que el rastreo contiene referencias a los locales de su pila, esto generaría una referencia circular y una fuga de memoria (temporal) hasta que el GC circular entre. (Por eso nunca debe almacenar el rastreo en una variable local ).

Casi lo único que se me ocurre es que monopatchee las stuff globales para que cuando piense que está atrapando a Exception , realmente esté detectando un tipo especializado y la excepción se propague a usted como la persona que llama:

module_containing_stuff.Exception = type("BogusException", (Exception,), {}) try: stuff() except Exception: import sys print sys.exc_info()


La respuesta a esta pregunta depende de la versión de Python que esté utilizando.

En Python 3

Es simple: las excepciones vienen equipadas con un atributo __traceback__ que contiene el traceback. Este atributo también se puede escribir, y se puede configurar cómodamente usando el método de excepciones with_traceback :

raise Exception("foo occurred").with_traceback(tracebackobj)

Estas características se describen mínimamente como parte de la documentación de raise .

Todo el crédito por esta parte de la respuesta debe ir a Vyctor, quien primero publicó esta información . Lo incluyo aquí solo porque esta respuesta está estancada en la parte superior, y Python 3 se está volviendo más común.

En Python 2

Es molestamente complejo. El problema con los rastreos es que tienen referencias a los marcos de pila, y los marcos de pila tienen referencias a los rastreos que tienen referencias a los marcos de pila que tienen referencias a ... usted obtiene la idea. Esto causa problemas para el recolector de basura. (Gracias a ecatmur por primero señalar esto).

La buena manera de resolver esto sería romper quirúrgicamente el ciclo después de abandonar la cláusula except , que es lo que hace Python 3. La solución Python 2 es mucho más fea: se le proporciona una función ad-hoc, sys.exc_info() , que solo funciona dentro de la cláusula except . Devuelve una tupla que contiene la excepción, el tipo de excepción y el rastreo para cualquier excepción que se esté manejando actualmente.

Por lo tanto, si está dentro de la cláusula except , puede usar el resultado de sys.exec_info() junto con el módulo de sys.exec_info() para hacer varias cosas útiles:

>>> import sys, traceback >>> def raise_exception(): ... try: ... raise Exception ... except Exception: ... ex_type, ex, tb = sys.exc_info() ... traceback.print_tb(tb) ... finally: ... del tb ... >>> raise_exception() File "<stdin>", line 3, in raise_exception

Sin embargo, como lo indica su edición, está tratando de obtener el rastreo que se habría imprimido si no se hubiera manejado su excepción, una vez que se haya procesado. Esa es una pregunta mucho más difícil. Desafortunadamente, sys.exc_info devuelve (None, None, None) cuando no se está manejando ninguna excepción. Otros sys attribues relacionados tampoco ayudan. sys.exc_traceback está en desuso y no está definido cuando no se está manejando ninguna excepción; sys.last_traceback parece perfecto, pero parece que solo se define durante las sesiones interactivas.

Si puede controlar cómo se genera la excepción, es posible que pueda utilizar inspect y una excepción personalizada para almacenar parte de la información. Pero no estoy del todo seguro de cómo funcionaría eso.

Para decir la verdad, atrapar y devolver una excepción es algo inusual de hacer. Esto podría ser una señal de que necesita refactorizar de todos modos.


Una forma de obtener traceback como una cadena de un objeto de excepción en Python 3:

import traceback # `e` is an exception object that you get from somewhere traceback_str = ''''.join(traceback.format_tb(e.__traceback__))

traceback.format_tb(...) devuelve una lista de cadenas. ''''.join(...) une. Para obtener más información, visite: https://docs.python.org/3/library/traceback.html#traceback.format_exc