如何使用日志 Python 模块写入文件?
- 2025-03-06 08:55:00
- admin 原创
- 69
问题描述:
如何使用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')
这五个部分按顺序执行以下操作:
设置输出文件(
filename=logname
)将其设置为附加(
filemode='a'
)而不是覆盖(filemode='w'
)确定输出消息的格式(
format=...
)确定输出日期和时间的格式(
datefmt='%Y-%m-%d %H:%M:%S'
)并确定其能接受的最低消息级别(
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')
扫码咨询,免费领取项目管理大礼包!