Comment écrire dans un fichier, en utilisant le module Python de journalisation?

128

Comment puis-je utiliser le module de journalisation en Python pour écrire dans un fichier? Chaque fois que j'essaie de l'utiliser, il imprime simplement le message.

Takkun
la source

Réponses:

171

Un exemple d'utilisation logging.basicConfigplutôt quelogging.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')

Dans l'ordre, les cinq parties font ce qui suit:

  1. définir le fichier de sortie ( filename=logname)
  2. définissez-le pour ajouter plutôt que remplacer ( filemode='a')
  3. déterminer le format du message de sortie (format=... )
  4. déterminer le format de l'heure de sortie ( datefmt='%H:%M:%S')
  5. et déterminez le niveau de message minimum qu'il acceptera ( level=logging.DEBUG).
thegrinner
la source
Le nom de fichier peut-il être un emplacement hdfs? Si oui, comment?
Augmentation de Jacob du
est-il possible de définir le chemin du fichier
neeraja
1
assurez-vous que ce n'est pas sous if __name__ == '__main__':si vous utilisez apache
Rami Alloush
@RamiAlloush pouvez-vous s'il vous plaît élaborer? Pourquoi donc? (curiosité :))
notihs
@notihs, le serveur n'exécute pas le fichier de script directement, donc la section ci if __name__ == '__main__':- dessous n'est pas exécutée.
Rami Alloush le
71

Tiré du " livre de recettes de journalisation ":

# 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)

Et vous êtes prêt à partir.

PS Assurez-vous de lire également le HOWTO de journalisation .

Eli Bendersky
la source
4
Pour répondre à votre première question, n'hésitez pas à regarder le titre de la question que j'ai posée. J'ai parcouru le lien que vous avez fourni et il a été utile. J'ai copié le code que vous m'avez donné et avais-je tort de supposer que je pourrais utiliser logger.info ("message") et logger.warning ("message") avec succès? J'ai pu écrire dans le fichier en utilisant logger.warning, mais logger.info ne semble pas écrire dans le fichier.
Takkun
Essayez de supprimer l'appel setLevel. En lisant la documentation du gestionnaire, il semble que tous les messages sont traités par défaut.
thegrinner
2
Je peux écrire dans un fichier uniquement en utilisant logger.warning("message"), je ne peux pas utiliser logger.info("message")ni logger.debug("message"). C'est un peu ennuyeux.
m3nda
3
L'exemple de code que @EliBendersky a écrit ne comporte pas une étape si vous souhaitez écrire des messages d'information / de débogage. L'enregistreur lui-même a besoin de son propre niveau de journalisation pour être configuré pour accepter ce niveau de messages de journalisation, par exemple logger.setLevel(logging.DEBUG). Les enregistreurs peuvent être configurés avec plusieurs gestionnaires; le niveau configuré dans le journal détermine le niveau de gravité des messages du journal à envoyer à chacun de ses gestionnaires, et les niveaux définis dans les gestionnaires déterminent les niveaux que le gestionnaire traitera. Notez que ceux qui souhaitent imprimer des messages d'information n'ont besoin de le définir qu'à la INFOfois dans le journal et dans le gestionnaire.
testworks
J'ai mis à jour l'exemple à faire logger.setLevel(logging.DEBUG)- merci pour les commentaires
Eli Bendersky
13

Je préfère utiliser un fichier de configuration. Cela me permet de changer les niveaux de journalisation, les emplacements, etc. sans changer de code lorsque je passe du développement à la publication. J'emballe simplement un fichier de configuration différent avec le même nom et avec les mêmes enregistreurs définis.

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()

Voici mon code pour le fichier de configuration du journal

#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
la source
1
Nommer le fichier avec une date nécessite un double %%en Python 3. par exempletime.strftime("%%Y%%m%%D")
AH
9

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

logging.basicConfig(filename='/path/to/your/log', level=....)
Gryphius
la source
1
Cela enregistre les logs dans le fichier, c'est bien. Et si avec cela, je voudrais qu'il enregistre également les sorties sur le terminal?
Rishabh Agrahari
La loggingdocumentation officielle du module le permet. Vous pouvez même choisir quels journaux vont dans le terminal et lesquels vont dans un fichier, et bien d'autres applications intéressantes. docs.python.org/3/howto/…
Daniel Hernandez
4

voici une façon plus simple de procéder. cette solution n'utilise pas de dictionnaire de configuration et utilise un gestionnaire de fichier de rotation, comme ceci:

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')

ou comme ça:

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 handlers doit être une variable itérable. logpath + filename et debug_level ne sont que des variables contenant les informations respectives. bien sûr, les valeurs des paramètres de fonction dépendent de vous.

la première fois que j'utilisais le module de journalisation, j'ai commis l'erreur d'écrire ce qui suit, ce qui génère une erreur de verrouillage de fichier du système d'exploitation (ce qui précède est la solution à cela):

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))

et Bob est ton oncle!

pdp
la source
3

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

La FileHandlerclasse, située dans le loggingpackage principal , envoie la sortie de journalisation vers un fichier disque.

COUP
la source
3
+1 Pour un exemple complet, voir le "tutoriel de base": docs.python.org/howto/logging.html#logging-to-a-file
Ferdinand Beyer
J'aime aussi le fait qu'il existe plusieurs types de FileHandlers différents pour diverses situations. ( WatchedFileHandler, RotatingFileHandler, Etc.)
Commission paritaire de recours
0
import sys
import logging

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

Cet exemple devrait fonctionner correctement. J'ai ajouté streamhandler pour la console. Les données du journal de la console et du gestionnaire de fichiers doivent être similaires.

    # 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
la source
0

Description du format

#%(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. 

Appel normal

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')

Production

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

Utilisation de Dict, Call values

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

Production

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
la source