Wie schreibe ich mit dem Python-Protokollierungsmodul in eine Datei?


127

Wie kann ich das Protokollierungsmodul in Python verwenden, um in eine Datei zu schreiben? Jedes Mal, wenn ich versuche, es zu verwenden, wird nur die Nachricht ausgedruckt.

Antworten:


172

Ein Beispiel für die Verwendung von logging.basicConfiganstattlogging.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')

In der Reihenfolge machen die fünf Teile Folgendes:

  1. setze die Ausgabedatei ( filename=logname)
  2. setze es auf Anhängen anstatt zu überschreiben ( filemode='a')
  3. Bestimmen Sie das Format der Ausgabenachricht ( format=...)
  4. Bestimmen Sie das Format der Ausgabezeit ( datefmt='%H:%M:%S')
  5. und bestimmen Sie die minimale Nachrichtenstufe, die akzeptiert wird ( level=logging.DEBUG).

Kann der Dateiname ein HDFS-Speicherort sein? Wenn ja, wie?
Augmented Jacob

ist es möglich, Dateipfad
festzulegen

1
if __name__ == '__main__':
Rami Alloush

@RamiAlloush kannst du bitte näher darauf eingehen? Warum ist das so? (Neugier :))
notihs

@notihs, der Server führt die Skriptdatei nicht direkt aus, sodass der folgende Abschnitt if __name__ == '__main__':nicht ausgeführt wird.
Rami Alloush

70

Entnommen aus dem " Logging Cookbook ":

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

Und du kannst loslegen.

PS Lesen Sie auch das Protokollierungs-HOWTO .


4
Um Ihre erste Frage zu beantworten, können Sie sich den Titel der von mir gestellten Frage ansehen. Ich habe den von Ihnen angegebenen Link durchgesehen und er war hilfreich. Ich habe den Code kopiert, den Sie mir gegeben haben, und habe ich zu Unrecht angenommen, dass ich logger.info ("message") und logger.warning ("message") erfolgreich verwenden kann? Ich konnte mit logger.warning in die Datei schreiben, aber logger.info scheint nicht in die Datei zu schreiben.
Takkun

Versuchen Sie, den Aufruf setLevel zu entfernen. Beim Lesen der Handler- Dokumente sieht es so aus, als würden alle Nachrichten standardmäßig verarbeitet.
Thegrinner

2
Ich kann nur mit logger.warning("message"), nicht mit logger.info("message")noch in eine Datei schreiben logger.debug("message"). Das ist ein bisschen nervig.
m3nda

3
Das Codebeispiel, das @EliBendersky geschrieben hat, fehlt 1 Schritt, wenn Sie Info- / Debug-Nachrichten schreiben möchten. Der Logger selbst benötigt eine eigene Protokollebene, um diese Ebene der Protokollierungsnachrichten zu akzeptieren, z logger.setLevel(logging.DEBUG). Logger können mit mehreren Handlern konfiguriert werden. Die im Logger konfigurierte Ebene bestimmt, welche Protokollnachrichten mit Schweregrad an die einzelnen Handler gesendet werden sollen, und die in den Handlern festgelegten Ebenen bestimmen, welche Ebenen der Handler verarbeiten wird. Beachten Sie, dass diejenigen, die Infomeldungen drucken möchten, dies nur INFOim Logger und im Handler festlegen müssen .
Testworks

Ich habe das Beispiel aktualisiert, um zu tun logger.setLevel(logging.DEBUG)- danke für die Kommentare
Eli Bendersky

13

Ich bevorzuge die Verwendung einer Konfigurationsdatei. Es ermöglicht mir, die Protokollierungsstufen, Speicherorte usw. zu wechseln, ohne den Code zu ändern, wenn ich von der Entwicklung zur Veröffentlichung übergehe. Ich packe einfach eine andere Konfigurationsdatei mit demselben Namen und denselben definierten Loggern.

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

Hier ist mein Code für die Protokollkonfigurationsdatei

#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

1
Das Benennen der Datei mit einem Datum erfordert %%in Python 3 das Doppelte. ZBtime.strftime("%%Y%%m%%D")
AH

9

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

logging.basicConfig(filename='/path/to/your/log', level=....)

1
Dadurch werden die Protokolle in der Datei gespeichert, das ist gut. Was ist, wenn ich zusammen damit auch die Ausgänge auf dem Terminal protokollieren möchte?
Rishabh Agrahari

Die offizielle loggingModuldokumentation erlaubt dies. Sie können sogar auswählen, welche Protokolle in das Terminal und welche in eine Datei und in viele weitere interessante Anwendungen gelangen. docs.python.org/3/howto/…
Daniel Hernandez

4

Hier ist ein einfacher Weg, um es zu tun. Diese Lösung verwendet kein Konfigurationswörterbuch und verwendet einen Rotationsdatei-Handler wie folgt:

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

oder so:

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

Die Handlervariable muss iterierbar sein. logpath + filename und debug_level sind nur Variablen, die die entsprechenden Informationen enthalten. Natürlich liegen die Werte für die Funktionsparameter bei Ihnen.

Als ich das Protokollierungsmodul zum ersten Mal verwendete, habe ich den Fehler gemacht, Folgendes zu schreiben, was zu einem Fehler beim Sperren der Betriebssystemdatei führt (das Obige ist die Lösung dafür):

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

und Bob ist dein Onkel!



0
import sys
import logging

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

0

Dieses Beispiel sollte gut funktionieren. Ich habe Streamhandler für die Konsole hinzugefügt. Die Daten des Konsolenprotokolls und des Dateihandlers sollten ähnlich sein.

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

0

Formatbeschreibung

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

Normale Art zu telefonieren

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

Ausgabe

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

Rufen Sie mit Dict Werte auf

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

Ausgabe

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!
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.