Python如何將控制臺輸出另存為日志文件
Python將控制臺輸出另存為日志文件
需求
在 PyCharm 中或者說運行 python 程序時會使用 print 輸出些過程信息、 traceback 異常信息 到控制臺,但是程序運行結(jié)束后記錄就沒有了,所以想著每次運行將信息顯示在控制臺的同時記錄到文件中。
方法一:使用 Logger 類(推薦)
自定義創(chuàng)建 Logger 類,結(jié)合 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 # 創(chuàng)建一個 logger logger = logging.getLogger(__name__) # logger 的等級 logger.setLevel(level=logging.INFO) # 創(chuàng)建一個 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的內(nèi)容??刂婆_上的信息不僅僅只有代碼中print的信息,區(qū)分控制臺重定向和標準輸出重定向。
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函數(shù)開頭啟動日志
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中只有內(nèi)容“1”,沒有l(wèi)og_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 &,這條命令多出了黑窗
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Python with關(guān)鍵字,上下文管理器,@contextmanager文件操作示例
這篇文章主要介紹了Python with關(guān)鍵字,上下文管理器,@contextmanager文件操作,結(jié)合實例形式分析了Python使用with關(guān)鍵字及上下文管理器、contextmanager進行文件打開、讀寫、關(guān)閉等操作的相關(guān)實現(xiàn)技巧,需要的朋友可以參考下2019-10-10PyQt QListWidget修改列表項item的行高方法
今天小編就為大家分享一篇PyQt QListWidget修改列表項item的行高方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-06-06python使用redis實現(xiàn)消息隊列(異步)的實現(xiàn)完整例程
本文主要介紹了python使用redis實現(xiàn)消息隊列(異步)的實現(xiàn)完整例程,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-01-01Python字符串處理實現(xiàn)單詞反轉(zhuǎn)
這篇文章主要為大家詳細介紹了Python字符串處理實現(xiàn)單詞反轉(zhuǎn)的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-06-06Python從Excel讀取數(shù)據(jù)并使用Matplotlib繪制成二維圖像
本課程實現(xiàn)使用 Python 從 Excel 讀取數(shù)據(jù),并使用 Matplotlib 繪制成二維圖像。這一過程中,將通過一系列操作來美化圖像,最終得到一個可以出版級別的圖像。本課程對于需要書寫實驗報告,學位論文,發(fā)表文章,做報告的學員具有較大價值2023-02-02