Registro de Python (nombre de la función, nombre del archivo, número de línea) usando un solo archivo
Estoy tratando de aprender cómo funciona una aplicación. Y para esto estoy insertando comandos de depuración como la primera línea del cuerpo de cada función con el objetivo de registrar el nombre de la función, así como el número de línea (dentro del código) donde envío un mensaje a la salida de registro. Finalmente, dado que esta aplicación se compone de muchos archivos, quiero crear un solo archivo de registro para que pueda comprender mejor el flujo de control de la aplicación.
Esto es lo que sé:
Para obteniendo el nombre de la función, puedo usar
function_name.__name__
pero no quiero usar el nombre_función (para poder copiar y pegar rápidamente unLog.info("Message")
genérico en el cuerpo de todas las funciones). Sé que esto podría hacerse en C usando la macro__func__
pero no estoy seguro sobre python.Para obtener el nombre del archivo y el número de línea, he visto que (y creo que) mi aplicación está usando la función Python
locals()
pero en una sintaxis que no estoy completamente consciente de por ejemplo:options = "LOG.debug('%(flag)s : %(flag_get)s' % locals())
y lo intenté usando comoLOG.info("My message %s" % locals())
que produce algo como{'self': <__main__.Class_name object at 0x22f8cd0>}
. ¿Alguna información sobre esto, por favor?Sé cómo usar el registro y agregarle un controlador para registrar un archivo, pero no estoy seguro de si se puede usar un solo archivo para registrar todos los mensajes de registro en el orden correcto de las llamadas a funciones en el proyecto.
Agradecería mucho cualquier ayuda.
Gracias!
2 answers
Usted tiene algunas preguntas marginalmente relacionadas aquí.
Comenzaré con la más fácil: (3). Usando logging
puede agregar todas las llamadas a un solo archivo de registro u otro destino de salida: estarán en el orden en que ocurrieron en el proceso.
Siguiente: (2). locals()
proporciona un dict del ámbito actual. Por lo tanto, en un método que no tiene otros argumentos, tiene self
en el ámbito, que contiene una referencia a la instancia actual. El truco que se está usando que te está golpeando es la cuerda formateo usando un dict como el RHS del operador %
. "%(foo)s" % bar
será reemplazado por cualquiera que sea el valor de bar["foo"]
.
Finalmente, puedes usar algunos trucos de introspección, similares a los utilizados por pdb
que pueden registrar más información:
def autolog(message):
"Automatically log the current function details."
import inspect, logging
# Get the previous frame in the stack, otherwise it would
# be this function!!!
func = inspect.currentframe().f_back.f_code
# Dump the message + the name of this function to the log.
logging.debug("%s: %s in %s:%i" % (
message,
func.co_name,
func.co_filename,
func.co_firstlineno
))
Esto registrará el mensaje pasado, más el nombre de la función (original), el nombre del archivo en el que aparece la definición y la línea en ese archivo. Echa un vistazo a inspect - Inspect live objects para más detalles.
As I mencionado en mi comentario anterior, también puede colocar en un mensaje de depuración interactivo pdb
en cualquier momento insertando la línea import pdb; pdb.set_trace()
y volviendo a ejecutar su programa. Esto le permite pasar por el código, inspeccionando los datos como desee.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-18 02:56:48
La respuesta correcta para esto es utilizar el ya proporcionado funcName
variable
import logging
logger = logging.getLogger('root')
FORMAT = "[%(filename)s:%(lineno)s - %(funcName)20s() ] %(message)s"
logging.basicConfig(format=FORMAT)
logger.setLevel(logging.DEBUG)
Luego, en cualquier lugar que desee, solo agregue:
logger.debug('your message')
Ejemplo de salida de un script en el que estoy trabajando ahora mismo:
[invRegex.py:150 - handleRange() ] ['[A-Z]']
[invRegex.py:155 - handleRepetition() ] [[<__main__.CharacterRangeEmitter object at 0x10ba03050>, '{', '1', '}']]
[invRegex.py:197 - handleMacro() ] ['\\d']
[invRegex.py:155 - handleRepetition() ] [[<__main__.CharacterRangeEmitter object at 0x10ba03950>, '{', '1', '}']]
[invRegex.py:210 - handleSequence() ] [[<__main__.GroupEmitter object at 0x10b9fedd0>, <__main__.GroupEmitter object at 0x10ba03ad0>]]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-17 13:02:41