python保存日志文件
一般写大型程序的时候,程序运行时间都比较长,将一些必要的输出保存到日志文件中是很有必要的。下面提供两种将输出保存到日志文件的方法。切换系统输出流将系统输出保存到日志文件的第一种方法是将系统输出流切换至文件句柄。import osimport sys# make a copy of original stdout routestdout_backup = sys.stdout# 日志文件目录file
一般写大型程序的时候,程序运行时间都比较长,将一些必要的输出保存到日志文件中是很有必要的。下面提供两种将输出保存到日志文件的方法,以及一种 非常实用的全局调用方法。
切换系统输出流
第一种方法是将系统输出流切换至文件句柄。
import os
import sys
# make a copy of original stdout route
stdout_backup = sys.stdout
# 日志文件目录
file_path="message"
if not os.path.exists(os.path.join(os.getcwd(),file_path)):
# os.getcwd()用于获取当前文件目录
os.mkdir(os.path.join(os.getcwd(),file_path))
log_file = open(os.path.join(file_path,'log.txt'), "w")
# redirect print output to log file
sys.stdout = log_file # 将系统输出切换至log_file
print ("Now all print info will be written to message.log")
# any command line that you will execute
log_file.close()
# restore the output to initial pattern
sys.stdout = stdout_backup #将系统输出切换回console
print ("Now this will be presented on screen")
这种方式可以将所有print函数打印的信息保存到日志文件中,但是这些信息无法同时显示在console中。
logging模块输出日志
为了实现同时输出到console和日志文件,可以使用logging模块输出日志。
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import logging
import os
import time
logger = logging.getLogger()
logger.setLevel(level=logging.DEBUG)
time_line = time.strftime('%Y%m%d%H%M', time.localtime(time.time()))
print(os.getcwd())
log_path=os.path.join(os.getcwd(),'message')
logfile = log_path + '/'+time_line + '.txt'
handler = logging.FileHandler(logfile,mode='w') # 输出到log文件的handler
# handler.setLevel(logging.INFO)
formatter = logging.Formatter("%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s")
handler.setFormatter(formatter)
console = logging.StreamHandler() # 输出到console的handler
console.setLevel(logging.WARNING)
logger.addHandler(handler)
logger.addHandler(console)
logger.debug('This is a debug message.')
logger.info('This is an info message.')
logger.warning('This is a warning message.')
logger.error('This is an error message.')
logger.critical('This is a critical message.')
DEBUG:打印全部的日志。详细的信息,通常只出现在诊断问题上。
INFO:打印 INFO、WARNING、ERROR、CRITICAL 级别的日志。确认一切按预期运行。
WARNING:打印 WARNING、ERROR、CRITICAL 级别的日志。表明一些问题在不久的将来,这个软件还能按预期工作。
ERROR:打印 ERROR、CRITICAL 级别的日志。更严重的问题,软件没能执行一些功能。
CRITICAL:打印 CRITICAL 级别。一个严重的错误,表明程序本身可能无法继续运行。
如果不设置Level,默认输出所有信息;如果设置Level为logging.WARNING,则输出WARNING级别以下的所有信息。
输出结果如下:
console
ssh://root@[my-ip-address]:22/root/miniconda3/envs/py36/bin/python -u /tmp/pycharm_project_982/pytorch-openpose-master/test.py
/tmp/pycharm_project_982/pytorch-openpose-master
This is a warning message.
This is an error message.
This is a critical message.
Process finished with exit code 0
202203311424.txt
2022-03-31 14:24:54,285 - test.py[line:30] - DEBUG: This is a debug message.
2022-03-31 14:24:54,285 - test.py[line:31] - INFO: This is an info message.
2022-03-31 14:24:54,285 - test.py[line:32] - WARNING: This is a warning message.
2022-03-31 14:24:54,286 - test.py[line:33] - ERROR: This is an error message.
2022-03-31 14:24:54,286 - test.py[line:34] - CRITICAL: This is a critical message.
更实用的方法(一次实现,全局调用)
为了更方便的使用logging模块输出日志,可以定义一个函数或类并添加在系统变量中,这样随时可以调用该函数(或类)。
- loggers.py(相比于上面的实现,添加了
projectpath()
函数用来读取工程的根目录,添加了colorlog
模块用来更改不同级别日志输出的颜色和明亮程度)
import logging
import os
import time
import colorlog
# 这里是为了永远将日志文件夹放在当前工程目录下,而不至于当项目下有多个子目录时
def projectpath():
pwd = os.getcwd()
while(len(pwd.split('\\'))>4):
pwd = os.path.dirname(pwd) # 向上退一级目录
# print(pwd)
return pwd
def __logfun(isfile=False):
# black, red, green, yellow, blue, purple, cyan(青) and white, bold(亮白色)
log_colors_config = {
'DEBUG': 'bold_white',
'INFO': 'bold',
'WARNING': 'yellow',
'ERROR': 'red',
'CRITICAL': 'bold_red', # 加bold后色彩变亮
}
logger = logging.getLogger()
# 输出到console
# logger.setLevel(level=logging.DEBUG)
logger.setLevel(level=logging.INFO) # 某些python库文件中有一些DEBUG级的输出信息,如果这里设置为DEBUG,会导致console和log文件中写入海量信息
console_formatter = colorlog.ColoredFormatter(
# fmt='%(log_color)s[%(asctime)s.%(msecs)03d] %(filename)s -> %(funcName)s line:%(lineno)d [%(levelname)s] : %(message)s',
fmt='%(log_color)s %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s',
# datefmt='%Y-%m-%d %H:%M:%S',
log_colors=log_colors_config
)
console = logging.StreamHandler() # 输出到console的handler
# console.setLevel(logging.DEBUG)
console.setFormatter(console_formatter)
logger.addHandler(console)
# 输出到文件
if isfile:
# 设置文件名
time_line = time.strftime('%Y%m%d%H%M', time.localtime(time.time()))
log_path=os.path.join(projectpath(),'log')
if not os.path.exists(log_path):
os.mkdir(log_path)
logfile = log_path + '/'+time_line + '.txt'
# 设置文件日志格式
filer = logging.FileHandler(logfile,mode='w') # 输出到log文件的handler
# filer.setLevel(level=logging.DEBUG)
file_formatter = logging.Formatter(
fmt='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
# formatter = logging.Formatter("%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s")
filer.setFormatter(file_formatter)
logger.addHandler(filer)
return logger
log=__logfun()
if __name__=='__main__':
log.debug('This is a debug message.')
log.info('This is an info message.')
log.warning('This is a warning message.')
log.error('This is an error message.')
log.critical('This is a critical message.')
-
注意
projectpath()
函数是为了永远将日志文件夹放在当前工程目录下,而不至于当项目下有多个子目录时,每个子目录下都分别有各自的日志(会很混乱)。 -
因为我所有的python项目都是在
E:\project_file\PyCharm
文件夹下放着的,例如E:\project_file\PyCharm\pytorch
,所以在函数中我定义循环继续的条件为while(len(pwd.split('\\'))>4)
(你需要根据你自己的项目文件夹更改一个数字
),这样log文件的绝对路径就会永远是E:\project_file\PyCharm\pytorch\log
。如果我换了一个项目project1
,那log文件的绝对路径就会变为E:\project_file\PyCharm\project1\log
。 -
将
loggers.py
放在D:\pythonpath
(可自行更改)目录下,然后在系统环境变量PYTHONPATH
中添加D:\pythonpath
(如果没有这个环境变量,新建一个即可)
-
此时就可以在任意python项目的python文件下
from loggers import log
了,由于os.getcwd()返回的是调用loggers的文件路径,所以不用担心日志会保存到loggers.py本身所在路径。
-
开始搭建项目时,可能只是想在控制台看一下输出信息,直接在原始文件中定义
isfile=False
即可。当整个项目很大时,可能需要保存历史日志,此时在原始文件中定义isfile=True
即可,非常方便。 -
注意,以后任何用到print的地方,用
log.info
替换即可,(warning、error、critical根据情况选择使用即可)。log.debug
不建议使用(注释中有说明)。
更多推荐
所有评论(0)