Je voudrais générer un nouveau fichier journal à chaque itération d'une boucle en Python en utilisant le module de journalisation. J'analyse des données dans une boucle for, où chaque itération de la boucle contient des informations sur un nouvel objet. Je souhaite générer un fichier journal par objet.
J'ai regardé la documentation du module de journalisation et il est possible de modifier le fichier journal à des intervalles de temps ou lorsque le fichier journal se remplit, mais je ne vois pas comment générer de manière itérative un nouveau fichier journal avec un nouveau nom. Je sais à l'avance combien d'objets sont dans la boucle.
Mon pseudo-code imaginé serait:
import logging for target in targets: logfile_name = f"{target}.log" logging.basicConfig(format='%(asctime)s - %(levelname)s : %(message)s', datefmt='%Y-%m/%dT%H:%M:%S', filename=logfile_name, level=logging.DEBUG) # analyse target infomation logging.info('log target info...')
Cependant, les informations de journalisation sont toujours ajoutées au premier fichier journal de la cible 1.
Existe-t-il un moyen de forcer un nouveau fichier journal au début de chaque boucle?
4 Réponses :
Voici une version fonctionnelle de ce problème. Je n'ai pu le faire fonctionner que si les cibles avaient déjà .log avant d'entrer dans la boucle, vous pouvez donc en ajouter un de plus avant d'entrer dans les cibles et remplacer toutes les cibles avec l'extension .log
import logging targets = ["a.log","b.log","c.log"] for target in targets: log = logging.getLogger(target) formatter = logging.Formatter('%(asctime)s - %(levelname)s : %(message)s', datefmt='%Y-%m/%dT%H:%M:%S') fileHandler = logging.FileHandler(target, mode='a') fileHandler.setFormatter(formatter) streamHandler = logging.StreamHandler() streamHandler.setFormatter(formatter) log.addHandler(fileHandler) log.addHandler(streamHandler) log.info('log target info...')
Ce n'est peut-être pas la meilleure solution, mais cela créera un nouveau fichier journal pour chaque itération. Ce que cela fait, c'est ajouter un nouveau gestionnaire de fichiers à chaque itération.
import logging targets = ["a", "b", "c"] logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) for target in targets: log_file = "{}.log".format(target) log_format = "|%(levelname)s| : [%(filename)s]--[%(funcName)s] : %(message)s" formatter = logging.Formatter(log_format) # create file handler and set the formatter file_handler = logging.FileHandler(log_file) file_handler.setFormatter(formatter) # add handler to the logger logger.addHandler(file_handler) # sample message logger.info("Log file: {}".format(target))
Plutôt que d'utiliser directement la journalisation
, vous devez utiliser des objets de journalisation. Consultez la documentation ici .
Créez un nouveau objet logger comme première instruction de la boucle. Voici une solution de travail.
import logging import sys def my_custom_logger(logger_name, level=logging.DEBUG): """ Method to return a custom logger with the given name and level """ logger = logging.getLogger(logger_name) logger.setLevel(level) format_string = ("%(asctime)s â %(name)s â %(levelname)s â %(funcName)s:" "%(lineno)d â %(message)s") log_format = logging.Formatter(format_string) # Creating and adding the console handler console_handler = logging.StreamHandler(sys.stdout) console_handler.setFormatter(log_format) logger.addHandler(console_handler) # Creating and adding the file handler file_handler = logging.FileHandler(logger_name, mode='a') file_handler.setFormatter(log_format) logger.addHandler(file_handler) return logger if __name__ == "__main__": for item in range(10): logger = my_custom_logger(f"Logger{item}") logger.debug(item)
Ceci écrit dans un fichier journal différent pour chaque itération.
J'ai marqué cela comme la réponse car elle donne la solution la plus propre des trois présentées à l'époque. Merci beaucoup pour votre aide à ce sujet. Cela fonctionne parfaitement.
Une fonction logger
définie de cette manière sera-t-elle interceptée par logger = logging.getLogger ()
si je veux l'utiliser pour enregistrer différents modules? Que faire si je souhaite créer un fichier pour chaque élément
?
@muammar, pour réutiliser ceci, vous devez passer cet objet de journalisation à la classe souhaitée. Ici, nous créons un enregistreur pour item
.
@Mithilesh_Kunal Je l'ai résolu comme décrit ci-dessous stackoverflow.com/a/56409646/1995261 . Merci pour votre réponse!
Ce n'est pas nécessairement la meilleure réponse mais a fonctionné pour mon cas, et je voulais juste la mettre ici pour de futures références. J'ai créé une fonction qui ressemble à ceci:
if __name__ == "__main__": for i in range(1, 11, 1): directory = "_{}".format(i) if not os.path.exists(directory): os.makedirs(directory) filename = directory + "/training.log" logger(filename=filename)
Comme vous pouvez le voir (vous devrez peut-être faire défiler le code ci-dessus pour voir la ligne return logger
), je j'utilise logging.basicConfig ()
. Tous les modules que j'ai dans mon paquet qui enregistrent des trucs, ont ce qui suit au début des fichiers:
import logging import other stuff logger = logging.getLogger() class SomeClass(object): def some_method(self): logger.info("Whatever") .... stuff
Lors d'une boucle, j'ai appelé les choses de cette façon: p>
def logger(filename, level=None, format=None): """A wrapper to the logging python module This module is useful for cases where we need to log in a for loop different files. It also will allow more flexibility later on how the logging format could evolve. Parameters ---------- filename : str Name of logfile. level : str, optional Level of logging messages, by default 'info'. Supported are: 'info' and 'debug'. format : str, optional Format of logging messages, by default '%(message)s'. Returns ------- logger A logger object. """ levels = {"info": logging.INFO, "debug": logging.DEBUG} if level is None: level = levels["info"] else: level = levels[level.lower()] if format is None: format = "%(message)s" # https://stackoverflow.com/a/12158233/1995261 for handler in logging.root.handlers[:]: logging.root.removeHandler(handler) logger = logging.basicConfig(filename=filename, level=level, format=format) return logger
J'espère que cela vous sera utile.