para online how hacer gui debugger debug como python debugging line-numbers inspect

how - python debugger online



Depuración de Python: obtener nombre de archivo y número de línea desde el que se llama una función? (3)

La función inspect.stack() devuelve una lista de registros de marco , comenzando con la persona que llama y saliendo, que puede usar para obtener la información que desea:

from inspect import getframeinfo, stack def debuginfo(message): caller = getframeinfo(stack()[1][0]) print "%s:%d - %s" % (caller.filename, caller.lineno, message) def grr(arg): debuginfo(arg) grr("aargh")

Salida :

example.py:8 - aargh

Actualmente estoy construyendo un sistema bastante complejo en Python, y cuando estoy depurando a menudo pongo simples declaraciones impresas en varios scripts. Para mantener una visión general, a menudo también quiero imprimir el nombre del archivo y el número de línea donde se encuentra la declaración de impresión. Por supuesto que puedo hacer eso manualmente, o con algo como esto:

from inspect import currentframe, getframeinfo print getframeinfo(currentframe()).filename + '':'' + str(getframeinfo(currentframe()).lineno) + '' - '', ''what I actually want to print out here''

que imprime algo como:

filenameX.py:273 - lo que realmente quiero imprimir aquí

Para hacerlo más simple, quiero poder hacer algo como:

print debuginfo(), ''what I actually want to print out here''

Así que lo puse en una función en algún lugar y traté de hacer:

from debugutil import debuginfo print debuginfo(), ''what I actually want to print out here'' print debuginfo(), ''and something else here''

desafortunadamente, me sale

debugutil.py:3 - what I actually want to print out here debugutil.py:3 - and something else here

Imprime el nombre del archivo y el número de línea en el que definí la función, en lugar de la línea en la que llamo debuginfo (). Esto es obvio, porque el código se encuentra en el archivo debugutil.py.

Entonces, mi pregunta es en realidad: ¿Cómo puedo obtener el nombre de archivo y el número de línea desde donde se llama a esta función debuginfo ()? Todos los consejos son bienvenidos!


Si coloca su código de rastreo en otra función, y lo llama desde su código principal, entonces debe asegurarse de obtener la información de la pila del abuelo, no del padre o la función de rastreo.

A continuación se muestra un ejemplo de sistema profundo de 3 niveles para aclarar aún más a qué me refiero. Mi función principal llama a una función de rastreo, que llama a otra función para hacer el trabajo.

###################################### import sys, os, inspect, time time_start = 0.0 # initial start time def trace_libary_init(): global time_start time_start = time.time() # when the program started def trace_library_do(relative_frame, msg=""): global time_start time_now = time.time() # relative_frame is 0 for current function (this one), # 1 for direct parent, or 2 for grand parent.. total_stack = inspect.stack() # total complete stack total_depth = len(total_stack) # length of total stack frameinfo = total_stack[relative_frame][0] # info on rel frame relative_depth = total_depth - relative_frame # length of stack there # Information on function at the relative frame number func_name = frameinfo.f_code.co_name filename = os.path.basename(frameinfo.f_code.co_filename) line_number = frameinfo.f_lineno # of the call func_firstlineno = frameinfo.f_code.co_firstlineno fileline = "%s:%d" % (filename, line_number) time_diff = time_now - time_start print("%13.6f %-20s %-24s %s" % (time_diff, fileline, func_name, msg)) ################################ def trace_do(msg=""): trace_library_do(1, "trace within interface function") trace_library_do(2, msg) # any common tracing stuff you might want to do... ################################ def main(argc, argv): rc=0 trace_libary_init() for i in range(3): trace_do("this is at step %i" %i) time.sleep((i+1) * 0.1) # in 1/10''s of a second return rc rc=main(sys.argv.__len__(), sys.argv) sys.exit(rc)

Esto imprimirá algo como:

$ python test.py 0.000005 test.py:39 trace_do trace within interface func 0.001231 test.py:49 main this is at step 0 0.101541 test.py:39 trace_do trace within interface func 0.101900 test.py:49 main this is at step 1 0.302469 test.py:39 trace_do trace within interface func 0.302828 test.py:49 main this is at step 2

La función trace_library_do () en la parte superior es un ejemplo de algo que puede colocar en una biblioteca y luego llamarla desde otras funciones de seguimiento. El valor de profundidad relativa controla qué entrada en la pila de python se imprime.

Mostré sacando algunos otros valores interesantes en esa función, como el número de línea de inicio de la función, la profundidad total de la pila y la ruta completa al archivo. No lo mostré, pero las variables globales y locales en la función también están disponibles para inspeccionar, así como el seguimiento completo de la pila a todas las demás funciones debajo de la suya. Hay más que suficiente información con lo que estoy mostrando arriba para hacer trazas jerárquicas de tiempo de llamada / retorno. En realidad, no es mucho más que crear las partes principales de su propio depurador de nivel de fuente desde aquí, y todo está en su mayoría esperando a ser utilizado.

Estoy seguro de que alguien se opondrá a que estoy usando campos internos con datos devueltos por las estructuras de inspección, ya que puede haber funciones de acceso que hagan lo mismo por usted. Pero los encontré al revisar este tipo de código en un depurador de Python, y al menos funcionan aquí. Estoy ejecutando python 2.7.12, sus resultados podrían muy bien si está ejecutando una versión diferente.

En cualquier caso, le recomiendo encarecidamente que importe el código de inspección en su propio código de Python, y observe lo que puede proporcionarle, especialmente si puede realizar un solo paso a través de su código en un buen depurador de Python. Aprenderá mucho sobre cómo funciona Python, y podrá ver los beneficios del lenguaje y lo que sucede detrás de la cortina para que esto sea posible.

El rastreo de nivel de fuente completo con marcas de tiempo es una excelente manera de mejorar su comprensión de lo que hace su código, especialmente en un entorno más dinámico en tiempo real. Lo mejor de este tipo de código de rastreo es que una vez que se escribe, no necesita soporte del depurador para verlo.


Simplemente ponga el código que publicó en una función:

from inspect import currentframe, getframeinfo def my_custom_debuginfo(message): print getframeinfo(currentframe()).filename + '':'' + str(getframeinfo(currentframe()).lineno) + '' - '', message

y luego utilízalo como quieras:

# ... some code here ... my_custom_debuginfo(''what I actually want to print out here'') # ... more code ...

Te recomiendo que pongas esa función en un módulo separado, de esa manera puedes reutilizarla cada vez que la necesites.