日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python写日志文件_Python logging日志模块 配置文件方式

發布時間:2023/12/15 python 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python写日志文件_Python logging日志模块 配置文件方式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在一些微服務或web服務中我們難免需要日志功能,用來記錄一些用戶的登錄記錄,操作記錄,以及一些程序的崩潰定位,執行訪問定位等等;

Python內置 非常強大的日志模塊 ==> logging 今天給大家分享一下以配置文件形式進行配置log日志 ;

Centos6.7

Python3.6

logging0.5.1.2

logging模塊有三個比較重要的功能組件:

1、loggers 配置文件可定義一些輸出日志的appname

2、handler 過濾器,比如設置日志的分隔大小,輸出位置,日志文件創建等

3、formatters 指定日志輸出的格式

1: 創建一個文件,以.conf結尾 或以.ini結尾(PS: 其他的結尾沒試過,你可以試試)

vim log.conf

2: 定義日志輸出的APP名,指定過濾器這里用loggers功能

[loggers] #固定寫法

keys=root,error,info #創建三個app名,root是父類,必需存在的

[logger_root] #創建完的app名我們要定義一些規則,嚴格要求格式為"logger_appname"

level=DEBUG #設置日志級別

qualname=root #這里在"root"appname下可以不填,所有沒獲取get的情況下默認app名都是root

handlers=debugs #設置指定過濾器,多個以逗號分隔,這個名字待會兒 我們會以固定格式"handler_(value)"創建

[logger_error]

level=ERROR

qualname=error #除了root appname以外,定義的app名必須要設置這個屬性,用于定義打印輸出時候的app名

handlers=errors

[logger_info]

level=INFO

qualname=INFO

handlers=infos

3: 定義日志過濾器這里用handler功能

[handlers] #固定格式

keys=infos,errors,debugs #定義過濾器名稱,下面定義以handler_keysname格式定義,上面引用名稱必須和keys一致

[handler_infos]

class=FileHandler #指定過濾器組件,詳情請看官網,這個是以文件方式創建

level=INFO #設置級別

formatter=form01 #定義日志打印格式,下面會創建formatters,格式也是嚴格要求formatter_keysname 創建

args=('info.log','a') #創建文件名字,以什么方式打開

[handler_errors]

class=FileHandler

level=DEBUG

formatter=form02

args=('info1.log','a')

[handler_debugs]

class=FileHandler

level=DEBUG

formatter=form02

args=('info1.log','a')

3: 定義日志輸出格式,這里我們介紹最后一個組件formatters

[formatters] #固定格式

keys=form01,form02 #定義名稱,下面會引用格式同上

[formatter_form01]

format=%(asctime)s %(filename)s %(levelname)s %(message)s #年-月-日 時-分-秒,毫秒,文件名,級別名,消息信息

datefmt=%Y-%m-%d %H:%M:%S #日期輸出格式

[formatter_form02]

format=%(asctime)s %(filename)s %(levelname)s %(message)s

datefmt=%Y-%m-%d %H:%M:%S

4: 具體程序引用

#!/usr/bin/env python

import logging

import logging.config

logging.config.fileConfig('log.conf')

logs = logging.getLogger('error')

logs.error('errorsssss')

補充知識:python按照日志等級將日志輸出至不同的日志文件

將日志按照等級分別保存在不同的文件中,并在控制臺同步輸出。

import os

import sys

import logging

from logs.multiprocessloghandler import MultiprocessHandler

def loggerDefine(platform, log_name):

base_dir = "F:\PythonProject\\xiao_new_resources\logs"

info_dir_path = base_dir + "\\info\\{}".format(platform)

error_dir_path = base_dir + "\\error\\{}".format(platform)

# 判斷響應的文件是否存在

if not os.path.exists(info_dir_path):

os.makedirs(info_dir_path)

info_dir = os.path.join(info_dir_path, log_name)

if not os.path.exists(error_dir_path):

os.makedirs(error_dir_path)

error_dir = os.path.join(error_dir_path, log_name)

# 返回一個logger對象,如果沒有指定名字將返回root logger

log = logging.getLogger('test')

# 定義日志輸出格式

formattler = '%(asctime)s|%(processName)s|%(threadName)s|%(levelname)s|%(filename)s:%(lineno)d|%(funcName)s|%(message)s'

fmt = logging.Formatter(formattler)

# 設置日志控制臺輸出

stream_handler = logging.StreamHandler(sys.stdout)

stream_handler.setLevel(logging.INFO)

# 設置控制臺文件輸出

log_handler_info = MultiprocessHandler(info_dir)

log_handler_err = MultiprocessHandler(error_dir)

# 設置日志輸出格式:

stream_handler.setFormatter(fmt)

log_handler_info.setFormatter(fmt)

log_handler_err.setFormatter(fmt)

# 設置過濾條件

info_filter = logging.Filter()

info_filter.filter = lambda record: record.levelno < logging.WARNING # 設置過濾等級

err_filter = logging.Filter()

err_filter.filter = lambda record: record.levelno >= logging.WARNING

# 對文件輸出日志添加過濾條件

log_handler_info.addFilter(info_filter)

log_handler_err.addFilter(err_filter)

# 對logger增加handler日志處理器

log.addHandler(log_handler_info)

log.addHandler(log_handler_err)

log.addHandler(stream_handler)

log.setLevel("INFO")

return log

if __name__ == '__main__':

logg = loggerDefine("youtube", "youtube.log")

logg.info("info")

logg.warning("warning")

logg.error("error")

multiprocessloghandler源碼:

import datetime

import logging

import os

import re

try:

import codecs

except ImportError:

codecs = None

class MultiprocessHandler(logging.FileHandler):

"""支持多進程的TimedRotatingFileHandler"""

def __init__(self, filename, when='D', backupCount=7, encoding="utf-8", delay=False):

"""

filename 日志文件名,when 時間間隔的單位,backupCount 保留文件個數

delay 是否開啟 OutSteam緩存

True 表示開啟緩存,OutStream輸出到緩存,待緩存區滿后,刷新緩存區,并輸出緩存數據到文件。

False表示不緩存,OutStrea直接輸出到文件

"""

self.prefix = filename

self.backupCount = backupCount

self.when = when.upper()

# 正則匹配 年-月-日

# 正則寫到這里就對了

self.extMath = r"\d{4}-\d{2}-\d{2}"

# S 每秒建立一個新文件

# M 每分鐘建立一個新文件

# H 每天建立一個新文件

# D 每天建立一個新文件

self.when_dict = {

'S': "%Y-%m-%d-%H-%M-%S",

'M': "%Y-%m-%d-%H-%M",

'H': "%Y-%m-%d-%H",

'D': "%Y-%m-%d"

}

# 日志文件日期后綴

self.suffix = self.when_dict.get(when)

# 源碼中self.extMath寫在這里

# 這個正則匹配不應該寫到這里,不然非D模式下 會造成 self.extMath屬性不存在的問題

# 不管是什么模式都是按照這個正則來搜索日志文件的。

# if self.when == 'D':

# 正則匹配 年-月-日

# self.extMath = r"^\d{4}-\d{2}-\d{2}"

if not self.suffix:

raise ValueError(u"指定的日期間隔單位無效: %s" % self.when)

# 拼接文件路徑 格式化字符串

self.filefmt = os.path.join(os.getcwd(), "%s.%s" % (self.prefix, self.suffix))

a = "%s.%s" % (self.prefix, self.suffix)

# 使用當前時間,格式化文件格式化字符串

self.filePath = datetime.datetime.now().strftime(self.filefmt)

# 獲得文件夾路徑

_dir = os.path.dirname(self.filefmt)

try:

# 如果日志文件夾不存在,則創建文件夾

if not os.path.exists(_dir):

os.makedirs(_dir)

except Exception:

print("創建文件夾失敗")

print("文件夾路徑:" + self.filePath)

pass

if codecs is None:

encoding = None

# 調用FileHandler

logging.FileHandler.__init__(self, self.filePath, 'a+', encoding, delay)

def shouldChangeFileToWrite(self):

"""更改日志寫入目的寫入文件

return True 表示已更改,False 表示未更改"""

# 以當前時間獲得新日志文件路徑

_filePath = datetime.datetime.now().strftime(self.filefmt)

# 新日志文件日期 不等于 舊日志文件日期,則表示 已經到了日志切分的時候

# 更換日志寫入目的為新日志文件。

# 例如 按 天 (D)來切分日志

# 當前新日志日期等于舊日志日期,則表示在同一天內,還不到日志切分的時候

# 當前新日志日期不等于舊日志日期,則表示不在

# 同一天內,進行日志切分,將日志內容寫入新日志內。

if _filePath != self.filePath:

self.filePath = _filePath

return True

return False

def doChangeFile(self):

"""輸出信息到日志文件,并刪除多于保留個數的所有日志文件"""

# 日志文件的絕對路徑

self.baseFilename = os.path.abspath(self.filePath)

# stream == OutStream

# stream is not None 表示 OutStream中還有未輸出完的緩存數據

if self.stream:

# self.stream.flush()

self.stream.close()

self.stream = None

# delay 為False 表示 不OutStream不緩存數據 直接輸出

# 所有,只需要關閉OutStream即可

if not self.delay:

# self.stream.close()

self.stream = self._open()

# 刪除多于保留個數的所有日志文件

if self.backupCount > 0:

for s in self.getFilesToDelete():

# print s

os.remove(s)

def getFilesToDelete(self):

"""獲得過期需要刪除的日志文件"""

# 分離出日志文件夾絕對路徑

# split返回一個元組(absFilePath,fileName)

# 例如:split('I:\ScripPython\char4\mybook\util\logs\mylog.2017-03-19)

# 返回(I:\ScripPython\char4\mybook\util\logs, mylog.2017-03-19)

# _ 表示占位符,沒什么實際意義,

dirName, _ = os.path.split(self.baseFilename)

fileNames = os.listdir(dirName)

result = []

# self.prefix 為日志文件名 列如:mylog.2017-03-19 中的 mylog

# 加上 點號 . 方便獲取點號后面的日期

prefix = self.prefix

prefix = _.rsplit(".", 1)[0] + "."

plen = len(prefix)

for fileName in fileNames:

if fileName[:plen] == prefix:

# 日期后綴 mylog.2017-03-19 中的 2017-03-19

suffix = fileName[plen:]

# 匹配符合規則的日志文件,添加到result列表中

if re.compile(self.extMath).match(suffix):

result.append(os.path.join(dirName, fileName))

result.sort()

# 返回 待刪除的日志文件

# 多于 保留文件個數 backupCount的所有前面的日志文件。

if len(result) < self.backupCount:

result = []

else:

result = result[:len(result) - self.backupCount]

return result

def emit(self, record):

"""發送一個日志記錄

覆蓋FileHandler中的emit方法,logging會自動調用此方法"""

try:

if self.shouldChangeFileToWrite():

self.doChangeFile()

logging.FileHandler.emit(self, record)

except (KeyboardInterrupt, SystemExit):

raise

except:

self.handleError(record)

以上這篇Python logging日志模塊 配置文件方式就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持腳本之家。

總結

以上是生活随笔為你收集整理的python写日志文件_Python logging日志模块 配置文件方式的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。