如何写一个文件,使用日志Python模块?

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

345272 次浏览

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

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

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

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

取自"日志食谱":

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

你可以开始了。

附注:一定要阅读日志HOWTO

一个使用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")


logger = logging.getLogger('urbanGUI')

按顺序,这五个部分做以下工作:

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

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

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
import sys
import logging


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

这个例子应该工作正常。我已经为控制台添加了流处理器。控制台 日志和文件处理程序数据应该类似

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

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

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

处理器变量需要是一个可迭代对象。Logpath +filename和debug_level只是变量 各自的信息。当然,函数参数的值是向上的 给你。< / p >

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

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

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

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)
  • < p > asctime

    % (asctime)

    创建日志记录的可读时间。默认情况下 格式为' 2003-07-08 16:49:45,896 '(逗号后面的数字 都是毫秒部分的时间)。

  • < p >创建

    %(创建)f

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

  • < p > exc_info

    你不需要自己格式化它。

    异常元组(à la sys.exc_info)或者,如果没有异常发生, 没有。< / p >

  • < p >文件名

    %(文件名)

    路径名的文件名部分。

  • < p > funcName

    % (funcName)

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

  • < p > levelname

    % (levelname)

    消息的文本日志级别('DEBUG', 'INFO', 'WARNING', “错误”、“重要”)。< / p >

  • < p > levelno

    % (levelno)

    消息的数字日志级别(DEBUG, INFO, WARNING, ERROR, 关键)。< / p >

  • < p > lineno

    % (lineno) d

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

  • < p >消息

    %(消息)

    日志消息,计算为msg % args。这个设置是在 Formatter.format()被调用

  • < p >模块

    %(模块)

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

  • < p >毫秒断开

    % d(毫秒断开)

    日志记录创建时间的毫秒部分。

  • < p >味精

    你不需要自己格式化它。

    原始日志调用中传递的格式字符串。合并了 args生成消息,或者一个任意对象(参见Using arbitrary . args)

  • < p >名称

    %(名称)

    用于记录呼叫的记录器名称。

  • < p >路径名

    %(路径)

    发出日志记录调用的源文件的完整路径名 (如果可用)。< / p >

  • < p >过程

    %(过程)d

    进程ID(如果可用)。

  • < p > processName

    % (processName)

    进程名(如果可用)。

  • < p > relativeCreated

    % (relativeCreated) d

    创建LogRecord的时间(以毫秒为单位)

    . log模块加载时间
  • < p > stack_info

    你不需要自己格式化它。

    的底部的堆栈帧信息(如果可用) 的堆栈帧,直到并包括的堆栈帧 导致创建此记录的日志调用
  • < p >线程

    %(线程)d

    线程ID(如果可用)。

  • < p > threadName

    % (threadName)

    线程名(如果可用)。

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

虽然这是一个老问题,但对于现在想问这个问题的人来说,你也可以使用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"]
}
})

或者另一个更具体的例子,在一个特定的目录下旋转文件:

today = datetime.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
},
...

最好干净的方法。

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