Cómo registrar el nombre del archivo de origen y el número de línea en Python


123

¿Es posible decorar / extender el sistema de registro estándar de Python, de modo que cuando se invoque un método de registro, también registre el archivo y el número de línea donde se invocó o tal vez el método que lo invocó?

Respuestas:


228

Seguro, verifique los formateadores en los documentos de registro. Específicamente las variables lineno y pathname.

% (nombre de ruta) s Nombre de ruta completo del archivo de origen donde se emitió la llamada de registro (si está disponible).

% (nombre de archivo) s Parte del nombre de archivo de la ruta.

% (módulo) s Módulo (parte del nombre del nombre del archivo).

% (funcName) s Nombre de la función que contiene la llamada de registro.

% (lineno) d Número de línea de origen donde se emitió la llamada de registro (si está disponible).

Se parece a esto:

formatter = logging.Formatter('[%(asctime)s] p%(process)s {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s','%m-%d %H:%M:%S')

1
Y, sí, se debe considerar el desorden de mayúsculas / minúsculas en las variables.
Tom Pohl

1
También denominado "caso camello muy mal implementado".
Jon Spencer

81

Además de la respuesta muy útil de Seb , aquí hay un fragmento de código útil que demuestra el uso del registrador con un formato razonable:

#!/usr/bin/env python
import logging

logging.basicConfig(format='%(asctime)s,%(msecs)d %(levelname)-8s [%(filename)s:%(lineno)d] %(message)s',
    datefmt='%Y-%m-%d:%H:%M:%S',
    level=logging.DEBUG)

logger = logging.getLogger(__name__)
logger.debug("This is a debug log")
logger.info("This is an info log")
logger.critical("This is critical")
logger.error("An error occurred")

Genera esta salida:

2017-06-06:17:07:02,158 DEBUG    [log.py:11] This is a debug log
2017-06-06:17:07:02,158 INFO     [log.py:12] This is an info log
2017-06-06:17:07:02,158 CRITICAL [log.py:13] This is critical
2017-06-06:17:07:02,158 ERROR    [log.py:14] An error occurred

5
Use esto para más detalles: formatter = logging.Formatter ('% (asctime) s,% (levelname) -8s [% (filename) s:% (module) s:% (funcName) s:% (lineno) d] % (message) s ')
Girish Gupta

¿Hay alguna manera de cambiar solo en un lugar en la parte superior del código si los mensajes de registro se imprimen o no? Me gustaría dos modos, uno con muchas impresiones para ver qué hace exactamente el programa; y uno, para cuando es lo suficientemente estable, donde no se muestra ningún resultado.
Marie. P.

3
@ Marie.P. no hagas preguntas diferentes en los comentarios. Sin embargo, la respuesta son los niveles de registro.
bugmenot123

4

Para construir sobre lo anterior de una manera que envíe el registro de depuración a la salida estándar:

import logging
import sys

root = logging.getLogger()
root.setLevel(logging.DEBUG)

ch = logging.StreamHandler(sys.stdout)
ch.setLevel(logging.DEBUG)
FORMAT = "[%(filename)s:%(lineno)s - %(funcName)20s() ] %(message)s"
formatter = logging.Formatter(FORMAT)
ch.setFormatter(formatter)
root.addHandler(ch)

logging.debug("I am sent to standard out.")

Poner lo anterior en un archivo llamado debug_logging_example.pyproduce la salida:

[debug_logging_example.py:14 -             <module>() ] I am sent to standard out.

Entonces, si desea desactivar el cierre de sesión, comentar root.setLevel(logging.DEBUG).

Para archivos individuales (por ejemplo, asignaciones de clases), he encontrado que esta es una forma mucho mejor de hacer esto en lugar de usar print()declaraciones. Donde le permite desactivar la salida de depuración en un solo lugar antes de enviarla.


1

Para los desarrolladores que usan PyCharm o Eclipse pydev, lo siguiente producirá un enlace al origen de la declaración de registro en la salida del registro de la consola:

import logging, sys, os
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG, format='%(message)s | \'%(name)s:%(lineno)s\'')
log = logging.getLogger(os.path.basename(__file__))


log.debug("hello logging linked to source")

Consulte los hipervínculos del archivo de origen de Pydev en la consola de Eclipse para una discusión e historia más largas.


0
# your imports above ...


logging.basicConfig(
    format='%(asctime)s,%(msecs)d %(levelname)-8s [%(pathname)s:%(lineno)d in 
    function %(funcName)s] %(message)s',
    datefmt='%Y-%m-%d:%H:%M:%S',
    level=logging.DEBUG
)

logger = logging.getLogger(__name__)

# your classes and methods below ...
# An naive Sample of usage:
try:
    logger.info('Sample of info log')
    # your code here
except Exception as e:
    logger.error(e)

A diferencia de las otras respuestas, esto registrará la ruta completa del archivo y el nombre de la función que pudo haber ocurrido un error. Esto es útil si tiene un proyecto con más de un módulo y varios archivos con el mismo nombre distribuidos en estos módulos.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.