【问题标题】:Python: How to create log file everyday using logging module?Python:如何使用日志模块每天创建日志文件?
【发布时间】:2022-03-16 22:31:17
【问题描述】:

我是 python 日志记录模块的新手。我想在我的应用程序处于运行状态时每天创建一个新的日志文件。

log file name - my_app_20170622.log
log file entries within time - 00:00:01 to 23:59:59

第二天我想用第二天的日期创建一个新的日志文件-

log file name - my_app_20170623.log
log file entries within time - 00:00:01 to 23:59:59

我正在使用 python 的日志记录模块。

我正在使用如下 -

log_level = int(log_level)
logger = logging.getLogger('simple')
logger.setLevel(log_level)
fh = logging.FileHandler(log_file_name)
fh.setLevel(log_level)
formatter = logging.Formatter(log_format)
fh.setFormatter(formatter)
logger.addHandler(fh)

他们在python的日志模块中是否有任何配置可以每天创建日志?

【问题讨论】:

标签: python logging


【解决方案1】:

你必须创建一个TimedRotatingFileHandler:

from logging.handlers import TimedRotatingFileHandler
logname = "my_app.log"
handler = TimedRotatingFileHandler(logname, when="midnight", interval=1)
handler.suffix = "%Y%m%d"
logger.addHandler(handler)

这段代码将创建一个my_app.log,但当当天午夜结束时,该日志将被移动到一个名为my_app.log.20170623 的新日志文件中。

我希望这会有所帮助。

【讨论】:

  • 这种“%Y%m%d”格式不会创建20170623。它会创建像my_app.log.2017-06-23这样的文件。为什么会这样?
  • 你是对的@kit,我犯了一个错误。请尝试固定的解决方案。后缀修改必须在处理程序中完成,而不是在记录器中。
  • 是的,我发布了正确的解决方案作为此问题的答案,以获得适当的文件名。
  • 嗨@kit,您为什么发布正确的解决方案作为答案?我的回答符合你的要求,不是吗?
【解决方案2】:

终于,我得到了正确答案,我想分享这个答案。

基本上,需要像下面这样创建一个TimedRotatingFileHandler -

log_format = "%(asctime)s - %(levelname)s - %(message)s"
log_level = 10
handler = TimedRotatingFileHandler("my_app.log", when="midnight", interval=1)
handler.setLevel(log_level)
formatter = logging.Formatter(log_format)
handler.setFormatter(formatter)

# add a suffix which you want
handler.suffix = "%Y%m%d"

#need to change the extMatch variable to match the suffix for it
handler.extMatch = re.compile(r"^\d{8}$") 

# finally add handler to logger    
logger.addHandler(handler)

上面的代码将为当天生成类似 my_app.log 的文件,为前一天生成 my_app.log.20170704 之类的文件。

希望对你有帮助。

【讨论】:

  • 为什么需要handler.extMatch 行?
  • 我们需要根据我们的要求更改此变量,例如如果我想要 20170704,即它的正则表达式应该是 ^\d{8}$
  • 你试过没有那行吗?在我写的回复中,没有它也可以工作。
  • 是的,我试过了,没有这条线就不行。
  • handler.setLevel(log_level) 这行让我困惑了几个小时,将其改为logger.setLevel(log_level)
【解决方案3】:

RotatingFileHandler

class RotatingFileHandler(  filename[, mode[, maxBytes[, backupCount]]])

返回RotatingFileHandler 的新实例。指定的文件被打开并用作记录的流。如果未指定模式,则使用a。默认情况下,文件无限增长。

RotatingFileHandler 允许我们在当前日志文件达到一定大小时将我们的日志语句轮换到一个新文件中。

在此示例中,我们将对其进行设置,以便当它达到 500 字节时,我们将旋转到一个新文件中,最多可备份 2 次。

import logging
import logging.handlers as handlers
import time

logger = logging.getLogger('my_app')
logger.setLevel(logging.INFO)

logHandler = handlers.RotatingFileHandler('app.log', maxBytes=500, backupCount=2)
logHandler.setLevel(logging.INFO)
logger.addHandler(logHandler)

def main():
    while True:
        time.sleep(1)
        logger.info("A Sample Log Statement")

main()

执行此操作后,您应该注意到每次 app.log 超过 500 个字节时,它就会关闭并重命名为 app.log.x,其中 x 的值会递增,直到达到我们设置的 backupCount 的值。

TimedRotatingFileHandler

class TimedRotatingFileHandler( filename [,when [,interval [,backupCount]]])

返回TimedRotatingFileHandler 的新实例。指定的文件被打开并用作记录的流。在旋转时,它还会设置文件名后缀。轮换基于时间和间隔的乘积发生。

你可以使用when来指定interval的类型。可能的值列表是,注意它们不区分大小写:

|   Value  |    Type of interval   |
|:--------:|:---------------------:|
|     S    |        Seconds        |
|     M    |        Minutes        |
|     H    |         Hours         |
|     D    |          Days         |
|     W    |  Week day (0=Monday)  |
| midnight | Roll over at midnight |

TimedRotatingFileHandler 允许我们按时间片捕获日志文件。

import logging
import logging.handlers as handlers
import time

logger = logging.getLogger('my_app')
logger.setLevel(logging.INFO)

logHandler = handlers.TimedRotatingFileHandler('timed_app.log', when='M', interval=1)
logHandler.setLevel(logging.INFO)
logger.addHandler(logHandler)

def main():
    while True:
        time.sleep(1)
        logger.info("A Sample Log Statement")

main()

运行此代码将无限期地每分钟创建新的日志文件。我们可以在logHandler 实例上设置backupCount 参数,它将限制我们创建的日志文件的数量。

使用适当的日志级别

使用TimedRotatingFileHandlerRotatingFileHandler 可以执行以下操作,例如将所有错误消息记录到旋转文件,但将所有正常日志文件记录到 TimedRotatingFileHandler,因为我们希望我们可以期待更多它们比错误消息。

两个级别的记录被拆分为两个不同的日志级别:INFOERROR 到两个不同的位置。

import logging
import logging.handlers as handlers
import time

logger = logging.getLogger('my_app')
logger.setLevel(logging.INFO)

## Here we define our formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

logHandler = handlers.TimedRotatingFileHandler('normal.log', when='M', interval=1, backupCount=0)
logHandler.setLevel(logging.INFO)
logHandler.setFormatter(formatter)

errorLogHandler = handlers.RotatingFileHandler('error.log', maxBytes=5000, backupCount=0)
errorLogHandler.setLevel(logging.ERROR)
errorLogHandler.setFormatter(formatter)

logger.addHandler(logHandler)
logger.addHandler(errorLogHandler)

def main():
    while True:
        time.sleep(1)
        logger.info("A Sample Log Statement")
        logger.error("An error log statement")

main()

您应该注意到,当您运行此程序时会创建 3 个日志文件。 error.log 将仅包含级别为 ERROR 或更高级别的日志。 normal.log 将包含从我们的应用程序中注销的所有日志消息的组合。

这些只是我认为在实现自己的日志系统时很重要的几件事。

【讨论】:

    【解决方案4】:

    TimedRotatingFileHandler 可用于此目的。请参考以下代码。

    from logging.config import dictConfig
    import logging
    
    dictConfig({
        'version': 1,
        'formatters': {
            'standard': {
                'format': '[%(asctime)s] %(levelname)s in %(module)s: %(message)s'
            }
        },
        'handlers': {
            'myapp_handler': {
                'class': 'logging.handlers.TimedRotatingFileHandler',
                'filename': './my_app.log',
                'when': 'd',
                'interval': 1,
                'backupCount': 30,
                'level': 'DEBUG',
                "encoding": "utf8",
                'formatter': 'standard'
            },
        },
        'loggers': {
            'simple': {
                'level': 'DEBUG',
                'handlers': ['myapp_handler']
            }
        },
    })
    
    
    logger = logging.getLogger("simple")
    
    logger.error("This is a test error")
    

    在上面的例子中,我使用了 dictConfig 来配置记录器。其他配置方式请参考链接:https://docs.python.org/3/library/logging.config.html

    一旦日期发生变化,记录器模块会通过在当前文件后面加上日期来创建一个新文件。

    【讨论】:

      【解决方案5】:

      我建议你看看logging.handlers.TimedRotatingFileHandler。 我想这就是你要找的。​​p>

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-05
        • 1970-01-01
        • 2014-11-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多