python - parentesis - Obtenga la descripción de la excepción y el seguimiento de la pila que causó una excepción, todo como una cadena
programa analizador de parentesis, llaves y corchetes "(){}[] " c++ (8)
Obtenga la descripción de la excepción y el seguimiento de la pila que causó una excepción, todo como una cadena
Para crear un stacktrace decentemente complicado para demostrar que obtenemos el stacktrace completo:
def raise_error():
raise RuntimeError(''something bad happened!'')
def do_something_that_might_error():
raise_error()
Registrando el apilamiento completo
Una buena práctica es tener un registrador configurado para su módulo. Sabrá el nombre del módulo y podrá cambiar los niveles (entre otros atributos, como los controladores)
import logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
Y podemos usar este registrador para obtener el error:
try:
do_something_that_might_error()
except Exception as error:
logger.exception(error)
Qué registros:
ERROR:__main__:something bad happened!
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "<stdin>", line 2, in do_something_that_might_error
File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!
Y así obtenemos la misma salida que cuando tenemos un error:
>>> do_something_that_might_error()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in do_something_that_might_error
File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!
Consiguiendo solo la cuerda
Si realmente solo quieres la cadena, usa la función traceback.format_exc
lugar, demostrando el registro de la cadena aquí
import traceback
try:
do_something_that_might_error()
except Exception as error:
just_the_string = traceback.format_exc()
logger.debug(just_the_string)
Qué registros:
DEBUG:__main__:Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "<stdin>", line 2, in do_something_that_might_error
File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!
He visto muchas publicaciones sobre el seguimiento de la pila y las excepciones en Python. Pero no he encontrado lo que necesito.
Tengo un fragmento de código de Python 2.7 que puede provocar una excepción. Me gustaría capturarlo y asignar a una cadena su descripción completa y el seguimiento de la pila que causó el error (simplemente todo lo que usamos para ver en la consola). Necesito esta cadena para imprimirla en un cuadro de texto en la GUI.
Algo como esto:
try:
method_that_can_raise_an_exception(params)
except Exception as e:
print_to_textbox(complete_exception_description(e))
El problema es: ¿cuál es la función complete_exception_description
?
Con Python 3, el siguiente código formateará un objeto de Exception
exactamente como se obtendría usando traceback.format_exc()
:
import traceback
try:
method_that_can_raise_an_exception(params)
except Exception as ex:
print(''''.join(traceback.format_exception(etype=type(ex), value=ex, tb=ex.__traceback__)))
La ventaja es que solo se necesita el objeto Exception
(gracias al atributo __traceback__
registrado) y, por lo tanto, se puede pasar más fácilmente como argumento a otra función para su procesamiento posterior.
Consulte el módulo de format_exc()
, específicamente la función format_exc()
. Here
import traceback
try:
raise ValueError
except:
tb = traceback.format_exc()
else:
tb = "No error"
finally:
print tb
He definido la siguiente clase de ayuda:
import traceback
class TracedExeptions(object):
def __init__(self):
pass
def __enter__(self):
pass
def __exit__(self, etype, value, tb):
if value :
if not hasattr(value, ''traceString''):
value.traceString = "/n".join(traceback.format_exception(etype, value, tb))
return False
return True
Que luego puedo usar así:
with TracedExeptions():
#some-code-which-might-throw-any-exception
Y luego puede consumirlo así:
def log_err(ex):
if hasattr(ex, ''traceString''):
print("ERROR:{}".format(ex.traceString));
else:
print("ERROR:{}".format(ex));
(Antecedentes: Me sentí frustrado por el uso de Promise
s junto con Exception
s, que desafortunadamente pasa las excepciones generadas en un lugar a un controlador on_rejected en otro lugar, y por lo tanto es difícil obtener el rastreo de la ubicación original)
Para aquellos que usan Python-3
Usando el módulo de traceback
y la exception.__traceback__
uno puede extraer el seguimiento de pila de la siguiente manera:
- agarrar la pila de seguimiento actual usando
traceback.extract_stack()
- elimine los últimos tres elementos (ya que son entradas en la pila que me llevaron a mi función de depuración)
- agregue el
__traceback__
del objeto de excepción usandotraceback.extract_tb()
- formatear todo usando
traceback.format_list()
import traceback
def exception_to_string(excp):
stack = traceback.extract_stack()[:-3] + traceback.extract_tb(excp.__traceback__) # add limit=??
pretty = traceback.format_list(stack)
return ''''.join(pretty) + ''/n {} {}''.format(excp.__class__,excp)
Una simple demostración:
def foo():
try:
something_invalid()
except Exception as e:
print(exception_to_string(e))
def bar():
return foo()
Obtenemos la siguiente salida cuando llamamos bar()
:
File "./test.py", line 57, in <module>
bar()
File "./test.py", line 55, in bar
return foo()
File "./test.py", line 50, in foo
something_invalid()
<class ''NameError''> name ''something_invalid'' is not defined
También puede considerar el uso del módulo Python cgitb , cgitb , para obtener información de excepción realmente buena y bien formateada, incluidos valores de variables locales, contexto de código fuente, parámetros de función, etc.
Por ejemplo para este código ...
import cgitb
cgitb.enable(format=''text'')
def func2(a, divisor):
return a / divisor
def func1(a, b):
c = b - 5
return func2(a, c)
func1(1, 5)
obtenemos esta salida de excepción ...
ZeroDivisionError
Python 3.4.2: C:/tools/python/python.exe
Tue Sep 22 15:29:33 2015
A problem occurred in a Python script. Here is the sequence of
function calls leading up to the error, in the order they occurred.
c:/TEMP/cgittest2.py in <module>()
7 def func1(a, b):
8 c = b - 5
9 return func2(a, c)
10
11 func1(1, 5)
func1 = <function func1>
c:/TEMP/cgittest2.py in func1(a=1, b=5)
7 def func1(a, b):
8 c = b - 5
9 return func2(a, c)
10
11 func1(1, 5)
global func2 = <function func2>
a = 1
c = 0
c:/TEMP/cgittest2.py in func2(a=1, divisor=0)
3
4 def func2(a, divisor):
5 return a / divisor
6
7 def func1(a, b):
a = 1
divisor = 0
ZeroDivisionError: division by zero
__cause__ = None
__class__ = <class ''ZeroDivisionError''>
__context__ = None
__delattr__ = <method-wrapper ''__delattr__'' of ZeroDivisionError object>
__dict__ = {}
__dir__ = <built-in method __dir__ of ZeroDivisionError object>
__doc__ = ''Second argument to a division or modulo operation was zero.''
__eq__ = <method-wrapper ''__eq__'' of ZeroDivisionError object>
__format__ = <built-in method __format__ of ZeroDivisionError object>
__ge__ = <method-wrapper ''__ge__'' of ZeroDivisionError object>
__getattribute__ = <method-wrapper ''__getattribute__'' of ZeroDivisionError object>
__gt__ = <method-wrapper ''__gt__'' of ZeroDivisionError object>
__hash__ = <method-wrapper ''__hash__'' of ZeroDivisionError object>
__init__ = <method-wrapper ''__init__'' of ZeroDivisionError object>
__le__ = <method-wrapper ''__le__'' of ZeroDivisionError object>
__lt__ = <method-wrapper ''__lt__'' of ZeroDivisionError object>
__ne__ = <method-wrapper ''__ne__'' of ZeroDivisionError object>
__new__ = <built-in method __new__ of type object>
__reduce__ = <built-in method __reduce__ of ZeroDivisionError object>
__reduce_ex__ = <built-in method __reduce_ex__ of ZeroDivisionError object>
__repr__ = <method-wrapper ''__repr__'' of ZeroDivisionError object>
__setattr__ = <method-wrapper ''__setattr__'' of ZeroDivisionError object>
__setstate__ = <built-in method __setstate__ of ZeroDivisionError object>
__sizeof__ = <built-in method __sizeof__ of ZeroDivisionError object>
__str__ = <method-wrapper ''__str__'' of ZeroDivisionError object>
__subclasshook__ = <built-in method __subclasshook__ of type object>
__suppress_context__ = False
__traceback__ = <traceback object>
args = (''division by zero'',)
with_traceback = <built-in method with_traceback of ZeroDivisionError object>
The above is a description of an error in a Python program. Here is
the original traceback:
Traceback (most recent call last):
File "cgittest2.py", line 11, in <module>
func1(1, 5)
File "cgittest2.py", line 9, in func1
return func2(a, c)
File "cgittest2.py", line 5, in func2
return a / divisor
ZeroDivisionError: division by zero
mis 2 centavos
import sys, traceback
try:
...
except Exception, e:
T, V, TB = sys.exc_info()
print ''''.join(traceback.format_exception(T,V,TB))
>>> import sys
>>> import traceback
>>> try:
... 5 / 0
... except ZeroDivisionError, e:
... type_, value_, traceback_ = sys.exc_info()
>>> traceback.format_tb(traceback_)
['' File "<stdin>", line 2, in <module>/n'']
>>> value_
ZeroDivisionError(''integer division or modulo by zero'',)
>>> type_
<type ''exceptions.ZeroDivisionError''>
>>>
>>> 5 / 0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero
Utiliza sys.exc_info () para recopilar la información y las funciones en el módulo de traceback
para formatearla. Here hay algunos ejemplos para formatearlo.
La cadena de excepción completa está en:
>>> ex = traceback.format_exception(type_, value_, traceback_)
>>> ex
[''Traceback (most recent call last):/n'', '' File "<stdin>", line 2, in <module>/n'', ''ZeroDivisionError: integer division or modulo by zero/n'']