如何使用日志 Python 模块写入文件?

2025-03-06 08:55:00
admin
原创
68
摘要:问题描述:如何使用Python 中的日志模块写入文件?每次我尝试使用它时,它只会打印出消息。解决方案 1:logging.basicConfig使用而不是的示例logging.fileHandler()logging.basicConfig(filename=logname, ...

问题描述:

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


解决方案 1:

logging.basicConfig使用而不是的示例logging.fileHandler()

logging.basicConfig(filename=logname,
                    filemode='a',
                    format='%(asctime)s,%(msecs)03d %(name)s %(levelname)s %(message)s',
                    datefmt='%Y-%m-%d %H:%M:%S',
                    level=logging.DEBUG)

logging.info("Running Urban Planning")

logger = logging.getLogger('urbanGUI')

这五个部分按顺序执行以下操作:

  1. 设置输出文件(filename=logname

  2. 将其设置为附加(filemode='a')而不是覆盖(filemode='w'

  3. 确定输出消息的格式(format=...

  4. 确定输出日期和时间的格式(datefmt='%Y-%m-%d %H:%M:%S'

  5. 并确定其能接受的最低消息级别(level=logging.DEBUG)。

解决方案 2:

摘自“日志食谱”:

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

您可以出发了。

PS 请务必阅读日志记录操作指南。

解决方案 3:

这里有两个示例,一个打印日志(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

解决方案 4:

我更喜欢使用配置文件。它允许我在从开发到发布时切换日志级别、位置等,而无需更改代码。我只需打包一个具有相同名称和相同定义记录器的不同配置文件即可。

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

解决方案 5:

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

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

解决方案 6:

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

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 只是保存相应信息的变量。当然,函数参数的值由您决定。

我第一次使用日志模块时犯了一个错误,写了下面的内容,产生了一个 OS 文件锁错误(上面是解决方案):

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

解决方案 7:

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

    # MUTHUKUMAR_TIME_DATE.py #>>>>>>>> file name(module)

    import sys
    import logging
    import logging.config
    # ================== Logger ================================
    def logger_func(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_func(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

解决方案 8:

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

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

解决方案 9:

import logging

from datetime import datetime

filename = datetime.now().strftime("%d-%m-%Y %H-%M-%S")#Setting the filename from current date and time
logging.basicConfig(filename=filename, filemode='a',
                    format="%(asctime)s, %(msecs)d %(name)s %(levelname)s [ %(filename)s-%(module)s-%(lineno)d ]  : %(message)s",
                    datefmt="%H:%M:%S",
                    level=logging.DEBUG)
  • 执行时间

%(asctime)s

LogRecord 的创建时间,方便用户阅读。默认情况下,格式为“2003-07-08 16:49:45,896”(逗号后的数字是时间的毫秒部分)。

  • 创建

%(已创建)f

LogRecord 的创建时间(由 time.time() 返回)。

  • 异常信息

您不需要自己进行格式化。

异常元组(à la sys.exc_info)或者,如果没有发生异常,则为 None。

  • 文件名

%(文件名)s

路径名的文件名部分。

  • 函数名称

%(函数名称)s

包含日志调用的函数名称。

  • 级别名称

%(级别名称)s

消息的文本日志记录级别(“DEBUG”、“INFO”、“WARNING”、“ERROR”、“CRITICAL”)。

  • 级别号

%(级别号)s

消息的数字日志记录级别(DEBUG、INFO、WARNING、ERROR、CRITICAL)。

  • 亚麻布

%(lineno)d

发出日志调用的源行号(如果可用)。

  • 信息

%(消息)s

记录的消息,计算为 msg % args。这是在调用 Formatter.format() 时设置的。

  • 模块

%(模块)

模块(文件名的名称部分)。

  • 毫秒

%(毫秒)d

LogRecord 创建时间的毫秒部分。

  • 信息

您不需要自己进行格式化。

原始日志记录调用中传递的格式字符串。与参数合并以生成消息或任意对象(请参阅使用任意对象作为消息)。

  • 姓名

%(姓名)

用于记录通话的记录器的名称。

  • 路径名

%(路径名)s

发出日志调用的源文件的完整路径名(如果可用)。

  • 过程

%(进程)d

进程 ID(如果可用)。

  • 进程名称

%(进程名称)s

进程名称(如果可用)。

  • 相对创建

%(相对创建)d

LogRecord 的创建时间(以毫秒为单位),相对于日志模块的加载时间。

  • 堆栈信息

您不需要自己进行格式化。

堆栈框架信息(如果可用)从当前线程堆栈的底部开始,直到导致创建此记录的日志记录调用的堆栈框架。

  • 线

%(线程)d

线程 ID(如果可用)。

  • 线程名称

%(线程名称)s

线程名称(如果可用)。

请前往官方python3 页面以获取有关日志记录的更多信息。

解决方案 10:

虽然这是一个老问题,但是对于最近遇到这个问题的人来说,你也可以使用dictConfig。例如,对于具有 info 级别及以上的文件:

logging.config.dictConfig({
    'version': 1,
    'formatters': {
        'default': {
            'format': '[%(asctime)s] %(message)s',
        }
    },
    'handlers': {
        'info': {
            'level': logging.INFO,
            'class': 'logging.FileHandler',
            'filename': 'info.log',
        },
    },
    "root": {
        "level": logging.INFO,
        "handlers": ["info"]
    }
})

或者另一个更具体地的例子,使用旋转文件并放在特定目录中:

import logging
from pathlib import Path
from datetime import date

today = date.today()
folder = './log'
Path(folder).mkdir(parents=True, exist_ok=False) # Create folder if not exists
logging.config.dictConfig({
        ...
        'info': {
            'level': logging.INFO,
            'class': 'logging.handlers.TimedRotatingFileHandler',
            'filename': f'{folder}/info-{today.month:02}-{today.year}.log',
            # Roll over on the first day of the weekday
            'when': 'W0',
            # Roll over at midnight
            'atTime': datetime.time(hour=0),
            # Number of files to keep.
            'backupCount': 8
        },
        ...

解决方案 11:

import sys
import logging

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

解决方案 12:

最好且最干净的方法。

    ds = datetime.now().strftime("%Y%m%d_%H%M%S")
    try:
        # py39 有force参数指定可能强制除去之前的handler,这里使用兼容写法,0708
        logging.getLogger().removeHandler(logging.getLogger().handlers[0])
        logging.getLogger().removeHandler(logging.getLogger().handlers[0])
    except:
        pass
    logging.basicConfig(
        # force=
        level=logging.INFO,
        format="%(asctime)s [%(levelname)s] %(message)s",
        handlers=[
            logging.FileHandler('log_%s_%s_%s.log' % (ds, create_net, os.path.basename(dataset_path))),
            logging.StreamHandler(sys.stdout)
        ]
    )
    logging.info('start train')
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2556  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1551  
  知识管理在企业发展中扮演着至关重要的角色,它能够帮助企业积累经验、提升创新能力并增强竞争力。PLM(产品生命周期管理)系统作为企业管理产品全生命周期的重要工具,其知识管理功能对于企业实现经验沉淀与复用具有不可忽视的作用。通过有效的知识管理机制,企业可以在PLM系统中更好地整合和利用产品相关的知识,从而优化产品开发流程、...
PLM项目管理软件   0  
  产品生命周期管理(PLM)和企业资源计划(ERP)是现代企业管理中至关重要的两个系统。它们在企业的运营和发展中发挥着不同但又相互关联的作用。对于企业管理者和相关从业者来说,清晰地理解PLM与ERP的核心区别,有助于更精准地运用这两个系统,提升企业的管理效率和竞争力。接下来,我们将深入剖析这两个系统的核心区别。定义与概念...
plm项目管理系统是什么   0  
  敏捷项目管理与产品生命周期管理(PLM)的融合以及六西格玛工具链的运用,正逐渐成为企业提升迭代效率、增强竞争力的关键策略。在快速变化的商业环境中,如何将敏捷项目管理的灵活性与PLM的全生命周期管控相结合,并借助六西格玛工具优化流程,是众多企业面临的重要课题。敏捷项目管理与PLM的基础认知敏捷项目管理强调灵活性、快速响应...
plm软件排行榜   0  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用