python 實(shí)現(xiàn)多進(jìn)程日志輪轉(zhuǎn)ConcurrentLogHandler
記錄日志是我們程序中必不可少的一個(gè)功能,但是日志文件如果沒有合理的管理,時(shí)間長了幾百兆的日志文件就很難分析了(都不想打開看),但是又不可能經(jīng)常手動(dòng)去管理它
日志輪轉(zhuǎn):根據(jù)時(shí)間或者文件大小控制日志的文件個(gè)數(shù),不用我們手動(dòng)管理
python中l(wèi)ogging模塊內(nèi)置的有幾個(gè)支持日志輪轉(zhuǎn)的handler
常用的有TimedRotatingFileHandler根據(jù)時(shí)間輪轉(zhuǎn) RotatingFileHandler根據(jù)文件大小輪轉(zhuǎn)
但是內(nèi)置的這些handler是多線程安全的,而不支持多進(jìn)程(可以修改源碼加鎖保證進(jìn)程安全)
多進(jìn)程的時(shí)候可以使用ConcurrentLogHandler(需要自行安裝)按照文件大小輪轉(zhuǎn)
pip install ConcurrentLogHandler
一、簡單的日志輪轉(zhuǎn)功能實(shí)現(xiàn):
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import logging
from cloghandler import ConcurrentRotatingFileHandler
from config import LOG_PATH, LOG_FILENAME, LOG_MAX_BYTES
def create_logger(log_path=os.getcwd(), # 存放日志的目錄
level=logging.DEBUG,
formatter=logging.BASIC_FORMAT, # 日志輸出格式
logger_name="", # 可以使用logging.getlogger(logger_name)使用此logger
mode='a',
delay=0,
debug=True,
log_filename=LOG_FILENAME, # 保存日志的文件名(備份出的文件會(huì)以此名+.1、 .2命名)
encoding=None,
maxBytes=LOG_MAX_BYTES, # 每個(gè)日志文件的最大容量
backupCount=3 # 最多備份幾個(gè)日志文件):
# 判斷存放日志的文件夾是否存在 如果不存在新建
if not os.path.exists(log_path):
os.mkdir(log_path)
# 存放log的文件名
log_filename = os.path.join(log_path, log_filename)
# 創(chuàng)建一個(gè)logger
logger = logging.getLogger(logger_name)
# 設(shè)置日志等級(jí)
logger.setLevel(level)
# 創(chuàng)建一個(gè)滾動(dòng)日志處理器
crfh = ConcurrentRotatingFileHandler(log_filename, mode=mode, maxBytes=maxBytes, backupCount=backupCount, delay=delay, debug=debug, encoding=encoding)
# 定義handler的輸出格式
# 設(shè)定日志輸出格式
crfh.setFormatter(formatter)
# 添加日志處理器
logger.addHandler(crfh)
# 返回logger對(duì)象
return logger
# 日志格式
formatter_log = logging.Formatter('%(asctime)s - %(filename)s [line: %(lineno)d] 【%(levelname)s】 ----- %(message)s')
# 生成一個(gè)logger
logger = create_logger(log_path=LOG_PATH, logger_name="mylogger", formatter=formatter_log)
這樣就可以在其他模塊導(dǎo)入logger進(jìn)行使用了
logger.error("error msg")
有時(shí)候我們會(huì)記錄一些數(shù)據(jù)到文件中,如果多個(gè)程序同時(shí)寫入同一文件會(huì)把數(shù)據(jù)寫亂 我們也可以使用這個(gè)模塊來代替f.write()
from config import CHANNEL_PATH, CHANNEL_FILENAME, LOG_MAX_BYTES
# 只需要把日志的格式改為只存入信息就可以了
formatter_writer = logging.Formatter('%(message)s')
# 創(chuàng)建一個(gè)寫入器(logger)
writer = create_logger(logger_name="writer",log_path=CHANNEL_PATH, log_filename=CHANNEL_FILENAME, formatter=formatter_writer, level=logging.INFO)
這樣就可以使用writer.info("msg")記錄數(shù)據(jù)了
二、使用ini配置文件
創(chuàng)建文件xxx.ini
[loggers]
keys = root,public
[handlers]
keys = consoleHandler,publicFileHandler
[formatters]
keys = my_formatter
[logger_root]
level = DEBUG
handlers = consoleHandler
[logger_public]
handlers = publicFileHandler
qualname = public
propagate = 0
[handler_consoleHandler]
class = StreamHandler
level = DEBUG
formatter = my_formatter
args = (sys.stdout,)
[handler_publicFileHandler]
class = cloghandler.ConcurrentRotatingFileHandler
level = INFO
formatter = my_formatter
kwargs = {"filename": "./logs/public.log", "maxBytes": 1024 * 1024 * 10, "backupCount": 10, "delay": True, "debug": True}
[formatter_my_formatter]
format = %(asctime)s - %(filename)s [line: %(lineno)d] [%(levelname)s] ----- %(message)s
datefmt = %Y-%m-%d %H:%M:%S
創(chuàng)建mylogger.py
import logging
import logging.config
logging.config.fileConfig("./xxx.ini")
logger = logging.getLogger("public")
logger.info("hello world!")
補(bǔ)充:python日志輪轉(zhuǎn)RotatingFileHandler動(dòng)態(tài)加載導(dǎo)致不能記錄日志問題
linux下:
Traceback (most recent call last): File “/usr/lib64/python2.7/logging/handlers.py”, line 77, in emit self.doRollover() File “/usr/lib64/python2.7/logging/handlers.py”, line 136, in doRollover os.rename(sfn, dfn) OSError: [Errno 13] Permission denied Logged from file utils.py, line 89
windows下:
Traceback (most recent call last): File “F:\Python27\lib\logging\handlers.py”, line 77, in emit self.doRollover() File “F:\Python27\lib\logging\handlers.py”, line 142, in doRollover os.rename(self.baseFilename, dfn) WindowsError: [Error 32] Logged from file utils.py, line 89
這是由于django開發(fā)模式時(shí)會(huì)同時(shí)啟動(dòng)兩個(gè)進(jìn)程加載settings.py,導(dǎo)致日志文件占用后無法重命名或者刪除
都知道django開發(fā)模式下如果有文件變動(dòng)會(huì)自動(dòng)重新啟動(dòng),所以同時(shí)又兩個(gè)進(jìn)程,一個(gè)是程序正常運(yùn)行的進(jìn)程,另一個(gè)是用來監(jiān)聽變更并重啟服務(wù)的進(jìn)程,他們都會(huì)加載一遍settings.py,可以在settings.py中加print然后啟動(dòng)會(huì)看到控制臺(tái)又兩次輸出。
解決方式:
python C:\Users\pc\Desktop\yunserver-1.1\manage.py runserver --noreload 0.0.0.0:8000
使用不動(dòng)態(tài)加載方式運(yùn)行(這樣可能會(huì)影響開發(fā)環(huán)境中動(dòng)態(tài)加載)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。
相關(guān)文章
基于python解析XML文件并將數(shù)據(jù)存儲(chǔ)到MongoDB的代碼示例
在軟件開發(fā)中,我們經(jīng)常需要處理各種格式的數(shù)據(jù),XML 是一種常用的數(shù)據(jù)交換格式,它可以存儲(chǔ)和傳輸結(jié)構(gòu)化數(shù)據(jù),很多網(wǎng)站會(huì)提供 XML 格式的數(shù)據(jù)接口,以便其他系統(tǒng)可以方便地獲取數(shù)據(jù),本文介紹了基于python解析XML文件并將數(shù)據(jù)存儲(chǔ)到MongoDB的代碼示例,需要的朋友可以參考下2024-06-06
關(guān)于Python函數(shù)參數(shù)的進(jìn)階用法
這篇文章主要給大家分享的是Python函數(shù)參數(shù)的進(jìn)階用法,Python函數(shù)的參數(shù)根據(jù)函數(shù) 在調(diào)用時(shí) 傳參的形式分為關(guān)鍵字參數(shù)和位置參數(shù),下面文章小編就來介紹相關(guān)資料,需要的朋友可以參考一下2021-10-10
Python編程中time模塊的一些關(guān)鍵用法解析
這篇文章主要介紹了Python編程中time模塊的一些關(guān)鍵用法解析,像mktime和localtime以及gmtime這些常用方法都有講到,需要的朋友可以參考下2016-01-01
Python Pygame實(shí)戰(zhàn)之打地鼠小游戲
Pygame庫是專門為了幫助做出的游戲和其他多媒體應(yīng)用Python編程語言的一個(gè)開放源代碼模塊。本文將利用Pygame模塊制作一個(gè)打地鼠的小游戲,快跟隨小編一起學(xué)習(xí)一下吧2022-01-01
教你用python實(shí)現(xiàn)一個(gè)加密的文字處理器
生活中有時(shí)候我們需要對(duì)一些重要的文件進(jìn)行加密,下面這篇文章主要給大家介紹了關(guān)于如何用python實(shí)現(xiàn)一個(gè)加密文字處理器的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-06-06
python+matplotlib演示電偶極子實(shí)例代碼
這篇文章主要介紹了python+matplotlib演示電偶極子實(shí)例代碼,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-01-01

