【问题标题】:How to write to a file, using the logging Python module?如何使用日志记录 Python 模块写入文件?
【发布时间】:2011-09-17 05:16:08
【问题描述】:

如何使用 Python 中的 logging 模块写入文件?每次我尝试使用它时,它都会打印出消息。

【问题讨论】:

  • 相关,如何在不创建记录器python的情况下记录警告?

标签: python logging


【解决方案1】:

这里有两个例子,一个打印日志(stdout),另一个将日志写入文件:

import logging
import sys

logger = logging.getLogger()
logger.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s | %(levelname)s | %(message)s')

stdout_handler = logging.StreamHandler(sys.stdout)
stdout_handler.setLevel(logging.DEBUG)
stdout_handler.setFormatter(formatter)

file_handler = logging.FileHandler('logs.log')
file_handler.setLevel(logging.DEBUG)
file_handler.setFormatter(formatter)


logger.addHandler(file_handler)
logger.addHandler(stdout_handler)

在这个例子中,所有的日志都将被打印出来,并被写入一个名为 logs.log 的文件中

使用示例:

logger.info('This is a log message!')
logger.error('This is an error message.')

所有内置日志处理程序列表https://docs.python.org/3/library/logging.handlers.html

【讨论】:

    【解决方案2】:

    这里有一个更简单的方法。此解决方案不使用 配置字典并使用旋转文件处理程序,如下所示:

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

    或者像这样:

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

    handlers 变量必须是可迭代的。 logpath+filename 和 debug_level 只是保存 相应的信息。当然,函数参数的值是向上的 给你。

    我第一次使用日志记录模块时犯了以下错误,这会产生操作系统文件锁定错误( 以上是解决方案):

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

    【讨论】:

      【解决方案3】:

      这个例子应该可以正常工作。我为控制台添加了流处理程序。安慰 日志和文件处理程序数据应该相似。

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

      【讨论】:

        【解决方案4】:

        取自“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)
        

        你可以走了。

        附:请务必阅读logging HOWTO

        【讨论】:

        • 要回答您的第一个问题,请随意查看我提出的问题的标题。我已经浏览了您提供的链接,这很有帮助。我已经复制了你给我的代码,我错误地认为我可以成功使用 logger.info("message") 和 logger.warning("message") 吗?我能够使用 logger.warning 写入文件,但是 logger.info 似乎没有写入文件。
        • 尝试删除 setLevel 调用。读取处理程序docs 似乎默认处理所有消息。
        • 我只能使用logger.warning("message") 写入文件,不能使用logger.info("message")logger.debug("message")。这有点烦人。
        • @EliBendersky 编写的代码示例缺少 1 步,如果您想编写信息/调试消息。记录器本身需要配置自己的日志级别以接受该级别的日志消息,例如logger.setLevel(logging.DEBUG)。记录器可以配置多个处理程序;记录器中配置的级别决定了将哪个严重级别的日志消息发送给每个处理程序,而处理程序中设置的级别决定了处理程序将处理哪些级别。请注意,那些想要打印信息消息的人只需要在记录器和处理程序中将其设置为INFO
        • 我已将示例更新为 logger.setLevel(logging.DEBUG) -- 感谢 cmets
        【解决方案5】:

        使用logging.basicConfig 而不是logging.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')
        

        五个部分依次执行以下操作:

        1. 设置输出文件(filename=logname)
        2. 将其设置为追加而不是覆盖 (filemode='a')
        3. 确定输出消息的格式 (format=...)
        4. 确定输出时间的格式(datefmt='%H:%M:%S'
        5. 并确定它将接受的最低消息级别 (level=logging.DEBUG)。

        【讨论】:

        • 文件名可以是hdfs位置吗?如果是,怎么做?
        • 如果在 apache 上运行,请确保它不在 if __name__ == '__main__':
        • @RamiAlloush 你能详细说明一下吗?这是为什么? (好奇:))
        • @notihs,服务器不直接运行脚本文件,所以if __name__ == '__main__':下面的部分不会被执行。
        • 我想指出的是,默认情况下,这个记录器不是线程安全的,它不会记录未捕获的异常,asctime 不能同时具有时区和毫秒,并且它不会同时记录到文件和打印到控制台。处理这些情况的一个选项是lovely-logger 模块——尽管它们都可以单独使用标准库来克服。
        【解决方案6】:
        import sys
        import logging
        
        from util import reducer_logfile
        logging.basicConfig(filename=reducer_logfile, format='%(message)s',
                            level=logging.INFO, filemode='w')
        

        【讨论】:

          【解决方案7】:

          我更喜欢使用配置文件。当我从开发到发布时,它允许我在不更改代码的情况下切换日志记录级别、位置等。我只是用相同的名称打包了一个不同的配置文件,并使用相同的定义记录器。

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

          这是我的日志配置文件代码

          #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
          

          【讨论】:

          • 用日期命名文件需要在 Python 3 中使用双 %%。例如time.strftime("%%Y%%m%%D")
          【解决方案8】:

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

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

          【讨论】:

          • 这样将日志保存在文件中,很好。如果与此一起,我也希望它在终端上记录输出怎么办?
          • 官方的logging 模块文档允许这样做。您甚至可以选择哪些日志进入终端,哪些日志进入文件,以及更多有趣的应用程序。 docs.python.org/3/howto/…
          【解决方案9】:

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

          位于核心logging 包中的FileHandler 类将日志输出发送到磁盘文件。

          【讨论】:

          猜你喜欢
          • 2014-02-01
          • 1970-01-01
          • 2020-01-04
          • 1970-01-01
          • 2019-12-08
          • 2014-10-21
          • 1970-01-01
          • 2020-08-11
          • 2017-12-26
          相关资源
          最近更新 更多