Python如何将控制台输出另存为日志文件
作者:渣渣的夏天 发布时间:2023-11-27 03:09:55
Python将控制台输出另存为日志文件
需求  
在 PyCharm 中或者说运行 python 程序时会使用 print 输出些过程信息、 traceback 异常信息 到控制台,但是程序运行结束后记录就没有了,所以想着每次运行将信息显示在控制台的同时记录到文件中。
方法一:使用 Logger 类(推荐)
自定义创建 Logger 类,结合 sys 进行记录控制台输出信息
demo.py
import sys
import os
import time
# 控制台输出记录到文件
class Logger(object):
? ? def __init__(self, file_name="Default.log", stream=sys.stdout):
? ? ? ? self.terminal = stream
? ? ? ? self.log = open(file_name, "a")
? ? def write(self, message):
? ? ? ? self.terminal.write(message)
? ? ? ? self.log.write(message)
? ? def flush(self):
? ? ? ? pass
if __name__ == '__main__':
? ? # 自定义目录存放日志文件
? ? log_path = './Logs/'
? ? if not os.path.exists(log_path):
? ? ? ? os.makedirs(log_path)
? ? # 日志文件名按照程序运行时间设置
? ? log_file_name = log_path + 'log-' + time.strftime("%Y%m%d-%H%M%S", time.localtime()) + '.log'
? ? # 记录正常的 print 信息
? ? sys.stdout = Logger(log_file_name)
? ? # 记录 traceback 异常信息
? ? sys.stderr = Logger(log_file_name)
? ? print(5555)
? ? print(2/0)
./Logs/log-20210103-140231.log
5555
Traceback (most recent call last):
File "G:\Codes\demo.py", line 33, in <module>
print(2/0)
ZeroDivisionError: division by zero
方法二:仅使用 sys
将所有输出全部直接保存到文件中,不再显示到控制台
demo.py
import sys
log_print = open('Defalust.log', 'w')
sys.stdout = log_print
sys.stderr = log_print
if __name__ == '__main__':
? ? print(555)
? ? print(2/0)
Default.log
555
Traceback (most recent call last):
File "G:\Codes\demo.py", line 9, in <module>
print(2/0)
ZeroDivisionError: division by zero
方法三:使用 logging 模块
功能更加全面,主要用于输出运行日志、设置输出日志的等级、日志保存路径等等
必须放到 try……catch…… 里面才能保存 traceback 的错误的信息,然后不能保存 print (如果要保存可以参考方法二,但是这样控制台就没有 print 了)
demo.py
import logging
import os
import time
import traceback
import sys
# 创建一个 logger
logger = logging.getLogger(__name__)
# logger 的等级
logger.setLevel(level=logging.INFO)
# 创建一个 handler,写入日志文件
log_path = './Logs/'
if not os.path.exists(log_path):
? ? os.makedirs(log_path)
log_file_name = log_path + 'log-' + time.strftime("%Y%m%d-%H%M%S", time.localtime()) + '.log'
logfile = log_file_name
handler = logging.FileHandler(logfile, mode='a+')
# 输入到日志文件中的日志等级
handler.setLevel(logging.DEBUG)
# 设置 handler 中日志记录格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
# 将 handler 添加到 logger 里面
logger.addHandler(handler)
# 将日志输出到控制台,默认 sys.stderr
logger.addHandler(logging.StreamHandler(sys.stdout))
logger.info("Start print log")
if __name__ == '__main__':
? ? try:
? ? ? ? print(5555555555)
? ? ? ? print(5/0)
? ? except Exception as e:
? ? ? ? logger.error(str(traceback.format_exc()))
log-20210103-151751.log
2021-01-03 15:17:51,597 - __main__ - INFO - Start print log
2021-01-03 15:17:51,597 - __main__ - ERROR - Traceback (most recent call last):
File "G:\Codes\demo.py", line 34, in <module>
print(5/0)
ZeroDivisionError: division by zero
Python记录日志,保存控制台输出
首先,保存控制台的信息不等于保存代码中的输出print的内容。控制台上的信息不仅仅只有代码中print的信息,区分控制台重定向和标准输出重定向。
1.仅保存代码中print的信息。即重定向标准输出。
定义日志类:
class Logger(object):
def __init__(self, filename='default.log', stream=sys.stdout):
self.terminal = stream
self.log = open(filename, 'a')
def write(self, message):
self.terminal.write(message)
self.log.write(message)
self.terminal.flush() # 不启动缓冲,实时输出
self.log.flush()
def flush(self):
pass
在main函数开头启动日志
sys.stdout = Logger('./log.log', sys.stdout)
sys.stderr = Logger('./log.log', sys.stderr)
例子:
import tensorflow as tf
import os, sys
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
os.environ["CUDA_VISIBLE_DEVICES"] = "2"
class Logger(object):
def __init__(self, filename='default.log', stream=sys.stdout):
self.terminal = stream
self.log = open(filename, 'a')
def write(self, message):
self.terminal.write(message)
self.log.write(message)
self.terminal.flush() # 不启动缓冲,实时输出
self.log.flush()
def flush(self):
pass
sys.stdout = Logger('./log.log', sys.stdout)
sys.stderr = Logger('./log.log', sys.stderr)
logit = tf.constant(1)
tf_config = tf.ConfigProto(log_device_placement=True)
sess = tf.Session(config=tf_config)
print(sess.run(logit))
此时log.log中只有内容“1”,没有log_device的信息,因为其不属于stdout/stderr,尽管控制台上有这些信息,
2.保存控制台上的所有信息。即控制台重定向。
测试代码:
# 控制台重定向
import tensorflow as tf
import os, time
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
logit = tf.constant(1)
tf_config = tf.ConfigProto(log_device_placement=True)
sess = tf.Session(config=tf_config)
print(sess.run(logit))
Linux下:
python3 -u train.py >> ./log.log 2>&1
nohup python3 -u train.py >> ./log.log 2>&1 &,不挂起后台运行
Windows下:
python -u test_gpu.py >> ./log.log 2>&1
start /min python -u test_gpu.py >> ./log.log 2>&1 &,这条命令多出了黑窗
来源:https://blog.csdn.net/qq_39564555/article/details/112135970


猜你喜欢
- let str = '这是一个字符串[html]语句;[html]字符串很常见';alert(str.replace(/\[
- 目录process模块1、在python中启动一个子进程2、给子进程传递参数3、同时开多个子进程4、join的用法5、多进程之间的数据是否隔
- 本文的重点就是如何创建一个PHP类来实现两个数间的加减乘除,这种类似于极简单的计算器功能。实现起来是非常简单的,继续往下看:这里简单给大家介
- python操作excel主要用到 xlrd 和 xlwt 这两个库,xlrd读取excel表格数据, 支持 xlsx和
- 本文实例讲述了Go语言服务器开发之客户端向服务器发送数据并接收返回数据的方法。分享给大家供大家参考。具体实现方法如下:package mys
- 前段时间写了个比较简单的批量水印添加的python实现方式,将某个文件夹下面的图片全部添加上水印。今天正好有时间就做了一个UI应用的封装,这
- 题目描述原题链接 :496. 下一个更大元素 I - 力扣(LeetCode) (leetcode-cn.com)nums1 中数
- 1.MySQL官网下载压缩版文件,放至安装路径下载zip安装包MySQL :: Download MySQL Community Serve
- 之前有聊过 golang 的协程,我发觉似乎还很理论,特别是在并发安全上,所以特结合网上的一些例子,来试验下go routine中 的 ch
- open 遍历一个大日志文件使用 readlines() 还是 readline() ?总体上 readlines() 不慢于python
- 最近需要将实验数据画图出来,由于使用python进行实验,自然使用到了matplotlib来作图。下面的代码可以作为画图的模板代码,代码中有
- 前言:Pandas 中应用 query 函数来进行数据筛选。query 函数的一般用法如下:df.query('expression
- 如果你有个5、6 G 大小的文件,想把文件内容读出来做一些处理然后存到另外的文件去,你会使用什么进行处理呢?不用在线等,给几个错误示范:有人
- Python中核心的数据类型有哪些?变量(数字、字符串、元组、列表、字典)什么是数据的不可变性?哪些数据类型具有不可变性数据的不可变是指数据
- 朴素贝叶斯估计朴素贝叶斯是基于贝叶斯定理与特征条件独立分布假设的分类方法。首先根据特征条件独立的假设学习输入/输出的联合概率分布,然后基于此
- 前言上一篇博文我们讲到了节流函数的应用场景,我们知道了节流函数可以用在模糊查询、scroller、onresize等场景;今天这篇我们来讲防
- 当程序中包含多个线程时,CPU 不是一直被特定的线程霸占,而是轮流执行各个线程。那么,CPU 在轮换执行线程的过程中,即从创建到消亡的整个过
- arguments.callee关于callee的解释:callee 是 arguments 对象的一个属性。可以用于引用该函数的函数体内当
- 本文利用python opencv进行图像的边缘检测,一般要经过如下几个步骤:1、去噪如cv2.GaussianBlur()等函数;2、计算
- 今天在使用Pycharm的时候,由于文件过多,我对目录下的文件做了归类,改动了一些文件的路径,结果后来执行的时候,出现了路径找不到的错误.新