¿Cómo escribir en un archivo, usando el módulo de registro de Python?

128

¿Cómo puedo usar el módulo de registro en Python para escribir en un archivo? Cada vez que intento usarlo, simplemente imprime el mensaje.

Takkun
fuente

Respuestas:

171

Un ejemplo de uso en logging.basicConfiglugar delogging.fileHandler()

logging.basicConfig(filename=logname,
                            filemode='a',
                            format='%(asctime)s,%(msecs)d %(name)s %(levelname)s %(message)s',
                            datefmt='%H:%M:%S',
                            level=logging.DEBUG)

logging.info("Running Urban Planning")

self.logger = logging.getLogger('urbanGUI')

En orden, las cinco partes hacen lo siguiente:

  1. establecer el archivo de salida ( filename=logname)
  2. configúrelo para agregar en lugar de sobrescribir ( filemode='a')
  3. determinar el formato del mensaje de salida ( format=...)
  4. determinar el formato de la hora de salida ( datefmt='%H:%M:%S')
  5. y determine el nivel mínimo de mensaje que aceptará ( level=logging.DEBUG).
thegrinner
fuente
¿Puede el nombre de archivo ser una ubicación de hdfs? Si es así, ¿cómo?
Jacob aumentado
¿Es posible establecer la ruta del archivo?
neeraja
1
asegúrese de que esto no sea inferior if __name__ == '__main__':si se ejecuta en apache
Rami Alloush
@RamiAlloush, ¿podrías explicarme? ¿Porqué es eso? (curiosidad :))
notihs
@notihs, el servidor no ejecuta el archivo de script directamente, por lo que la siguiente sección if __name__ == '__main__':no se ejecuta.
Rami Alloush
71

Tomado del " libro de recetas de registro ":

# create logger with 'spam_application'
logger = logging.getLogger('spam_application')
logger.setLevel(logging.DEBUG)
# create file handler which logs even debug messages
fh = logging.FileHandler('spam.log')
fh.setLevel(logging.DEBUG)
logger.addHandler(fh)

Y estás listo para irte.

PD: Asegúrate de leer también el CÓMO de registro .

Eli Bendersky
fuente
4
Para responder a su primera pregunta, siéntase libre de mirar el título de la pregunta que hice. He repasado el enlace que proporcionaste y fue útil. He copiado el código que me dio y ¿me equivoqué al asumir que podría usar logger.info ("mensaje") y logger.warning ("mensaje") correctamente? Pude escribir en el archivo usando logger.warning, sin embargo, logger.info no parece escribir en el archivo.
Takkun
Intente eliminar la llamada setLevel. Al leer los documentos del controlador , parece que todos los mensajes se procesan de forma predeterminada.
thegrinner
2
Puedo escribir en un archivo solo usando logger.warning("message"), no puedo usar logger.info("message")ni logger.debug("message"). Eso es un poco molesto.
m3nda
3
Al ejemplo de código que ha escrito @EliBendersky le falta 1 paso si desea escribir mensajes de información / depuración. El registrador en sí necesita su propio nivel de registro para ser configurado para aceptar ese nivel de mensajes de registro, por ejemplo logger.setLevel(logging.DEBUG). Los registradores se pueden configurar con varios controladores; el nivel configurado en el registrador determina qué mensajes de registro de nivel de gravedad enviar a cada uno de sus controladores, y los niveles establecidos en los controladores determinan qué niveles procesará el controlador. Tenga en cuenta que aquellos que quieran imprimir mensajes de información solo necesitan configurar esto INFOtanto en el registrador como en el controlador.
testworks
He actualizado la muestra para hacer logger.setLevel(logging.DEBUG)- gracias por los comentarios
Eli Bendersky
13

Prefiero usar un archivo de configuración. Me permite cambiar los niveles de registro, las ubicaciones, etc. sin cambiar el código cuando paso del desarrollo al lanzamiento. Simplemente empaqueto un archivo de configuración diferente con el mismo nombre y con los mismos registradores definidos.

import logging.config
if __name__ == '__main__':
    # Configure the logger
    # loggerConfigFileName: The name and path of your configuration file
    logging.config.fileConfig(path.normpath(loggerConfigFileName))

    # Create the logger
    # Admin_Client: The name of a logger defined in the config file
    mylogger = logging.getLogger('Admin_Client')

    msg='Bite Me'
    myLogger.debug(msg)
    myLogger.info(msg)
    myLogger.warn(msg)
    myLogger.error(msg)
    myLogger.critical(msg)

    # Shut down the logger
    logging.shutdown()

Aquí está mi código para el archivo de configuración de registro

#These are the loggers that are available from the code
#Each logger requires a handler, but can have more than one
[loggers]
keys=root,Admin_Client


#Each handler requires a single formatter
[handlers]
keys=fileHandler, consoleHandler


[formatters]
keys=logFormatter, consoleFormatter


[logger_root]
level=DEBUG
handlers=fileHandler


[logger_Admin_Client]
level=DEBUG
handlers=fileHandler, consoleHandler
qualname=Admin_Client
#propagate=0 Does not pass messages to ancestor loggers(root)
propagate=0


# Do not use a console logger when running scripts from a bat file without a console
# because it hangs!
[handler_consoleHandler]
class=StreamHandler
level=DEBUG
formatter=consoleFormatter
args=(sys.stdout,)# The comma is correct, because the parser is looking for args


[handler_fileHandler]
class=FileHandler
level=DEBUG
formatter=logFormatter
# This causes a new file to be created for each script
# Change time.strftime("%Y%m%d%H%M%S") to time.strftime("%Y%m%d")
# And only one log per day will be created. All messages will be amended to it.
args=("D:\\Logs\\PyLogs\\" + time.strftime("%Y%m%d%H%M%S")+'.log', 'a')


[formatter_logFormatter]
#name is the name of the logger root or Admin_Client
#levelname is the log message level debug, warn, ect 
#lineno is the line number from where the call to log is made
#04d is simple formatting to ensure there are four numeric places with leading zeros
#4s would work as well, but would simply pad the string with leading spaces, right justify
#-4s would work as well, but would simply pad the string with trailing spaces, left justify
#filename is the file name from where the call to log is made
#funcName is the method name from where the call to log is made
#format=%(asctime)s | %(lineno)d | %(message)s
#format=%(asctime)s | %(name)s | %(levelname)s | %(message)s
#format=%(asctime)s | %(name)s | %(module)s-%(lineno) | %(levelname)s | %(message)s
#format=%(asctime)s | %(name)s | %(module)s-%(lineno)04d | %(levelname)s | %(message)s
#format=%(asctime)s | %(name)s | %(module)s-%(lineno)4s | %(levelname)-8s | %(message)s

format=%(asctime)s | %(levelname)-8s | %(lineno)04d | %(message)s


#Use a separate formatter for the console if you want
[formatter_consoleFormatter]
format=%(asctime)s | %(levelname)-8s | %(filename)s-%(funcName)s-%(lineno)04d | %(message)s
Bill Kidd
fuente
1
Nombrar el archivo con una fecha requiere el doble %%en Python 3. por ejemplotime.strftime("%%Y%%m%%D")
AH
9

http://docs.python.org/library/logging.html#logging.basicConfig

logging.basicConfig(filename='/path/to/your/log', level=....)
Gryphius
fuente
1
Esto guarda los registros en el archivo, eso es bueno. ¿Qué pasa si junto con esto, me gustaría registrar las salidas en el terminal también?
Rishabh Agrahari
La loggingdocumentación oficial del módulo lo permite. Incluso puedes elegir qué registros van a la terminal y cuáles van a un archivo, y muchas más aplicaciones interesantes. docs.python.org/3/howto/…
Daniel Hernandez
4

aquí hay una forma más sencilla de hacerlo. esta solución no usa un diccionario de configuración y usa un controlador de archivos de rotación, así:

import logging
from logging.handlers import RotatingFileHandler

logging.basicConfig(handlers=[RotatingFileHandler(filename=logpath+filename,
                     mode='w', maxBytes=512000, backupCount=4)], level=debug_level,
                     format='%(levelname)s %(asctime)s %(message)s', 
                    datefmt='%m/%d/%Y%I:%M:%S %p')

logger = logging.getLogger('my_logger')

o así:

import logging
from logging.handlers import RotatingFileHandler

handlers = [
            RotatingFileHandler(filename=logpath+filename, mode='w', maxBytes=512000, 
                                backupCount=4)
           ]
logging.basicConfig(handlers=handlers, level=debug_level, 
                    format='%(levelname)s %(asctime)s %(message)s', 
                    datefmt='%m/%d/%Y%I:%M:%S %p')

logger = logging.getLogger('my_logger')

la variable de los manejadores debe ser iterable. logpath + filename y debug_level son solo variables que contienen la información respectiva. por supuesto, los valores para los parámetros de la función dependen de usted.

la primera vez que estaba usando el módulo de registro cometí el error de escribir lo siguiente, lo que genera un error de bloqueo del archivo del sistema operativo (lo anterior es la solución):

import logging
from logging.handlers import RotatingFileHandler

logging.basicConfig(filename=logpath+filename, level=debug_level, format='%(levelname)s %(asctime)s %(message)s', datefmt='%m/%d/%Y
 %I:%M:%S %p')

logger = logging.getLogger('my_logger')
logger.addHandler(RotatingFileHandler(filename=logpath+filename, mode='w', 
                  maxBytes=512000, backupCount=4))

¡y Bob es tu tío!

pdp
fuente
3

http://docs.python.org/library/logging.handlers.html#filehandler

La FileHandlerclase, ubicada en el loggingpaquete principal , envía la salida del registro a un archivo de disco.

PINCHAZO
fuente
3
+1 Para ver un ejemplo completo, consulte el "tutorial básico": docs.python.org/howto/logging.html#logging-to-a-file
Ferdinand Beyer
También me gusta cómo hay varios tipos diferentes de mensajes de correo FileHandlerelectrónico para diversas situaciones. ( WatchedFileHandler, RotatingFileHandler, Etc.)
JAB
0
import sys
import logging

from util import reducer_logfile
logging.basicConfig(filename=reducer_logfile, format='%(message)s',
                    level=logging.INFO, filemode='w')
Saurabh
fuente
0

Este ejemplo debería funcionar bien. He agregado streamhandler para consola. El registro de la consola y los datos del controlador de archivos deben ser similares.

    # MUTHUKUMAR_TIME_DATE.py #>>>>>>>> file name(module)

    import sys
    import logging
    import logging.config
    # ================== Logger ================================
    def Logger(file_name):
        formatter = logging.Formatter(fmt='%(asctime)s %(module)s,line: %(lineno)d %(levelname)8s | %(message)s',
                                      datefmt='%Y/%m/%d %H:%M:%S') # %I:%M:%S %p AM|PM format
        logging.basicConfig(filename = '%s.log' %(file_name),format= '%(asctime)s %(module)s,line: %(lineno)d %(levelname)8s | %(message)s',
                                      datefmt='%Y/%m/%d %H:%M:%S', filemode = 'w', level = logging.INFO)
        log_obj = logging.getLogger()
        log_obj.setLevel(logging.DEBUG)
        # log_obj = logging.getLogger().addHandler(logging.StreamHandler())

        # console printer
        screen_handler = logging.StreamHandler(stream=sys.stdout) #stream=sys.stdout is similar to normal print
        screen_handler.setFormatter(formatter)
        logging.getLogger().addHandler(screen_handler)

        log_obj.info("Logger object created successfully..")
        return log_obj
    # =======================================================


MUTHUKUMAR_LOGGING_CHECK.py #>>>>>>>>>>> file name
# calling **Logger** function
file_name = 'muthu'
log_obj =Logger(file_name)
log_obj.info("yes   hfghghg ghgfh".format())
log_obj.critical("CRIC".format())
log_obj.error("ERR".format())
log_obj.warning("WARN".format())
log_obj.debug("debug".format())
log_obj.info("qwerty".format())
log_obj.info("asdfghjkl".format())
log_obj.info("zxcvbnm".format())
# closing file
log_obj.handlers.clear()

OUTPUT:
2019/07/13 23:54:40 MUTHUKUMAR_TIME_DATE,line: 17     INFO | Logger object created successfully..
2019/07/13 23:54:40 MUTHUKUMAR_LOGGING_CHECK,line: 8     INFO | yes   hfghghg ghgfh
2019/07/13 23:54:40 MUTHUKUMAR_LOGGING_CHECK,line: 9 CRITICAL | CRIC
2019/07/13 23:54:40 MUTHUKUMAR_LOGGING_CHECK,line: 10    ERROR | ERR
2019/07/13 23:54:40 MUTHUKUMAR_LOGGING_CHECK,line: 11  WARNING | WARN
2019/07/13 23:54:40 MUTHUKUMAR_LOGGING_CHECK,line: 12    DEBUG | debug
2019/07/13 23:54:40 MUTHUKUMAR_LOGGING_CHECK,line: 13     INFO | qwerty
2019/07/13 23:54:40 MUTHUKUMAR_LOGGING_CHECK,line: 14     INFO | asdfghjkl
2019/07/13 23:54:40 MUTHUKUMAR_LOGGING_CHECK,line: 15     INFO | zxcvbnm

Thanks, 
muthukumar
fuente
0

Descripción del formato

#%(name)s       Name of the logger (logging channel).
#%(levelname)s  Text logging level for the message ('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL').
#%(asctime)s    Human-readable time when the LogRecord was created. By default this is of the form ``2003-07-08 16:49:45,896'' (the numbers after the comma are millisecond portion of the time).
#%(message)s    The logged message. 

Forma normal de llamar

import logging
#logging.basicConfig(level=logging.INFO)
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
logger.info('Start reading database')
# read database here
records = {'john': 55, 'tom': 66}
logger.debug('Records: %s', records)
logger.info('Updating records ...')
# update records here
logger.info('Finish updating records')

Salida

INFO:__main__:Start reading database
DEBUG:__main__:Records: {'john': 55, 'tom': 66}
INFO:__main__:Updating records ...
INFO:__main__:Finish updating records

Usando Dict, valores de llamada

import logging
import logging.config
import otherMod2

def main():
    """
    Based on http://docs.python.org/howto/logging.html#configuring-logging
    """
    dictLogConfig = {
        "version":1,
        "handlers":{
                    "fileHandler":{
                        "class":"logging.FileHandler",
                        "formatter":"myFormatter",
                        "filename":"config2.log"
                        }
                    },        
        "loggers":{
            "exampleApp":{
                "handlers":["fileHandler"],
                "level":"INFO",
                }
            },

        "formatters":{
            "myFormatter":{
                "format":"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
                }
            }
        }

    logging.config.dictConfig(dictLogConfig)

    logger = logging.getLogger("exampleApp")

    logger.info("Program started")
    result = otherMod2.add(7, 8)
    logger.info("Done!")

if __name__ == "__main__":
    main()

otherMod2.py

import logging
def add(x, y):
    """"""
    logger = logging.getLogger("exampleApp.otherMod2.add")
    logger.info("added %s and %s to get %s" % (x, y, x+y))
    return x+y

Salida

2019-08-12 18:03:50,026 - exampleApp - INFO - Program started
2019-08-12 18:03:50,026 - exampleApp.otherMod2.add - INFO - added 7 and 8 to get 15
2019-08-12 18:03:50,027 - exampleApp - INFO - Done!
sim
fuente