Python如何將控制臺(tái)輸出另存為日志文件
Python將控制臺(tái)輸出另存為日志文件
需求
在 PyCharm 中或者說(shuō)運(yùn)行 python 程序時(shí)會(huì)使用 print 輸出些過(guò)程信息、 traceback 異常信息 到控制臺(tái),但是程序運(yùn)行結(jié)束后記錄就沒(méi)有了,所以想著每次運(yùn)行將信息顯示在控制臺(tái)的同時(shí)記錄到文件中。
方法一:使用 Logger 類(lèi)(推薦)
自定義創(chuàng)建 Logger 類(lèi),結(jié)合 sys 進(jìn)行記錄控制臺(tái)輸出信息
demo.py
import sys
import os
import time
# 控制臺(tái)輸出記錄到文件
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)
? ? # 日志文件名按照程序運(yùn)行時(shí)間設(shè)置
? ? 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
將所有輸出全部直接保存到文件中,不再顯示到控制臺(tái)
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 模塊
功能更加全面,主要用于輸出運(yùn)行日志、設(shè)置輸出日志的等級(jí)、日志保存路徑等等
必須放到 try……catch…… 里面才能保存 traceback 的錯(cuò)誤的信息,然后不能保存 print (如果要保存可以參考方法二,但是這樣控制臺(tái)就沒(méi)有 print 了)
demo.py
import logging
import os
import time
import traceback
import sys
# 創(chuàng)建一個(gè) logger
logger = logging.getLogger(__name__)
# logger 的等級(jí)
logger.setLevel(level=logging.INFO)
# 創(chuàng)建一個(gè) handler,寫(xiě)入日志文件
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+')
# 輸入到日志文件中的日志等級(jí)
handler.setLevel(logging.DEBUG)
# 設(shè)置 handler 中日志記錄格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
# 將 handler 添加到 logger 里面
logger.addHandler(handler)
# 將日志輸出到控制臺(tái),默認(rèn) 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記錄日志,保存控制臺(tái)輸出
首先,保存控制臺(tái)的信息不等于保存代碼中的輸出print的內(nèi)容??刂婆_(tái)上的信息不僅僅只有代碼中print的信息,區(qū)分控制臺(tái)重定向和標(biāo)準(zhǔn)輸出重定向。
1.僅保存代碼中print的信息。即重定向標(biāo)準(zhǔn)輸出。
定義日志類(lèi):
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() # 不啟動(dòng)緩沖,實(shí)時(shí)輸出
self.log.flush()
def flush(self):
pass在main函數(shù)開(kāi)頭啟動(dòng)日志
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() # 不啟動(dòng)緩沖,實(shí)時(shí)輸出
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))此時(shí)log.log中只有內(nèi)容“1”,沒(méi)有l(wèi)og_device的信息,因?yàn)槠洳粚儆趕tdout/stderr,盡管控制臺(tái)上有這些信息,
2.保存控制臺(tái)上的所有信息。即控制臺(tái)重定向。
測(cè)試代碼:
# 控制臺(tái)重定向 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 &,不掛起后臺(tái)運(yùn)行
Windows下:
python -u test_gpu.py >> ./log.log 2>&1
start /min python -u test_gpu.py >> ./log.log 2>&1 &,這條命令多出了黑窗

總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
jupyter notebook遠(yuǎn)程訪(fǎng)問(wèn)不了的問(wèn)題解決方法
這篇文章主要介紹了jupyter notebook遠(yuǎn)程訪(fǎng)問(wèn)不了的問(wèn)題解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01
Python實(shí)現(xiàn)string字符串連接的方法總結(jié)【8種方式】
這篇文章主要介紹了Python實(shí)現(xiàn)string字符串連接的方法,結(jié)合實(shí)例形式總結(jié)分析了Python實(shí)現(xiàn)字符串連接的8種常見(jiàn)操作技巧,需要的朋友可以參考下2018-07-07
詳解pyinstaller selenium python3 chrome打包問(wèn)題
這篇文章主要介紹了詳解pyinstaller selenium python3 chrome打包問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10
Python導(dǎo)入或執(zhí)行python源文件的3種方法
這篇文章主要給大家介紹了關(guān)于Python導(dǎo)入或執(zhí)行python源文件的3種方法,python源代碼的文件以"py"為擴(kuò)展名,由python.exe解釋,可以在控制臺(tái)下運(yùn)行,需要的朋友可以參考下2023-08-08
Python?pyecharts案例超市4年數(shù)據(jù)可視化分析
這篇文章主要介紹了Python?pyecharts案例超市4年數(shù)據(jù)可視化分析,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-08-08
Python實(shí)現(xiàn)遍歷數(shù)據(jù)庫(kù)并獲取key的值
本文給大家分享的是Python實(shí)現(xiàn)遍歷數(shù)據(jù)庫(kù)并獲取key的值的方法,主要是使用for循環(huán)來(lái)實(shí)現(xiàn),有需要的小伙伴可以參考下。2015-05-05

