亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Python使用logging實(shí)現(xiàn)多進(jìn)程安全的日志模塊

 更新時(shí)間:2024年01月23日 08:07:43   作者:花酒鋤作田  
這篇文章主要為大家詳細(xì)介紹了Python如何使用標(biāo)準(zhǔn)庫logging實(shí)現(xiàn)多進(jìn)程安全的日志模塊,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解下

前言

原本應(yīng)用的日志是全部輸出到os的stdout,也就是控制臺輸出。因其它團(tuán)隊(duì)要求也要保留日志文件,便于他們用其他工具統(tǒng)一采集,另一方面還要保留控制臺輸出,便于出問題的時(shí)候自己直接看pod日志。具體需求如下:

  • 日志支持同時(shí)控制臺輸出和文件輸出
  • 控制臺的輸出級別可以高點(diǎn),比如WARNING,個(gè)人這邊的實(shí)際情況是WARNING或ERROR就能判斷大部分問題。日志文件的輸出級別設(shè)置為INFO,如果控制臺日志找不到問題,可以具體看日志文件的內(nèi)容。
  • 因?yàn)橛玫搅硕噙M(jìn)程,所以寫文件的時(shí)候要保證多進(jìn)程安全,避免日志內(nèi)容不會(huì)缺失。
  • 日志文件可以設(shè)置自動(dòng)分割,避免長時(shí)間不清理導(dǎo)致硬盤存儲(chǔ)資源浪費(fèi)。

因?yàn)椴辉试S隨便使用第三方包,所以只能用標(biāo)準(zhǔn)庫的logging。一開始想的方法比較挫——對文件加鎖,但改來改去發(fā)現(xiàn)根本不能給別人review。翻python官方文檔的時(shí)候發(fā)現(xiàn)logging庫有個(gè)QueueHandlerQueueListener,簡單試了下感覺邏輯還算清楚,遂簡單整理了下代碼。

示例代碼

目錄結(jié)構(gòu)如下,main.py是入口腳本,logs目錄和app.log將有程序運(yùn)行時(shí)自動(dòng)生成,主要日志功能放在pkg/log.py文件中。pkg/__init__.py為空文件,僅用于標(biāo)識為python包。

.
├── main.py
├── logs
│   └── app.log
└── pkg
    ├── __init__.py
    └── log.py

pkg/log.py內(nèi)容如下,主要提供logger已經(jīng)配置好的日志對象,該對象先將日志記錄到QueueHandler,然后QueueListener從隊(duì)列中取日志,并分別輸出到控制臺和日志文件中。close_log_queue()方法將在主進(jìn)程結(jié)束時(shí)調(diào)用。

import logging
from logging.handlers import TimedRotatingFileHandler, QueueHandler, QueueListener
import sys
import os
# from queue import Queue
from multiprocessing import Queue

log_queue = Queue(-1)
queue_listener = ""


logdir = "logs"
logfile = f"{logdir}/app.log"
if not os.path.exists(logdir):
    os.makedirs(logdir, exist_ok=True)

def set_formatter():
    """設(shè)置日志格式化器"""
    fmt = "%(asctime)s | %(levelname)s | %(name)s | %(filename)s:%(lineno)d | %(funcName)s | %(message)s"
    datefmt = "%Y-%m-%d %H:%M:%S"
    return logging.Formatter(fmt, datefmt=datefmt)

def set_queue_handler():
    # 不要給QueueHandler重復(fù)設(shè)置formatter, 會(huì)引起重復(fù)嵌套
    handler = QueueHandler(log_queue)
    handler.setLevel(logging.INFO)
    return handler
def set_stream_handler(formatter: logging.Formatter):
    # 輸出到控制臺的日志處理器
    handler = logging.StreamHandler(sys.stdout)
    handler.setLevel(logging.WARNING)
    handler.setFormatter(formatter)
    return handler

def set_timed_rotating_file_handler(formatter: logging.Formatter):
    # 輸出到文件的日志處理器, 每天生成一個(gè)新文件, 最多保留10個(gè)文件
    handler = TimedRotatingFileHandler(logfile, when="midnight", backupCount=10, encoding="utf-8")
    handler.setLevel(logging.INFO)
    handler.setFormatter(formatter)
    return handler

def close_log_queue():
    # 關(guān)閉隊(duì)列監(jiān)聽器
    global queue_listener
    if queue_listener:
        queue_listener.stop()

def get_logger(name: str = "mylogger", level: int = logging.INFO):
    logger = logging.getLogger(name)
    logger.setLevel(level)

    formatter = set_formatter()

    stream_handler = set_stream_handler(formatter)
    file_handler = set_timed_rotating_file_handler(formatter)
    queue_handler = set_queue_handler()

    logger.addHandler(queue_handler)

    global queue_listener
    if not queue_listener:
        queue_listener = QueueListener(log_queue, stream_handler, file_handler, respect_handler_level=True)
        queue_listener.start()

    return logger


logger = get_logger()

if __name__ == "__main__":
    logger.info("test")
    close_log_queue()

main.py內(nèi)容如下,主要是創(chuàng)建子進(jìn)程調(diào)用logger,觀察日志輸出是否正常。

from multiprocessing import Process
from pkg.log import logger, close_log_queue
import os

class MyProcess(Process):
    def __init__(self, delay):
        self.delay = delay
        super().__init__()

    def run(self):
        for i in range(self.delay):
            logger.info(f"pid: {os.getpid()}, {i}")

if __name__ == '__main__':
    logger.info(f"main process pid: {os.getpid()}")
    for i in range(10):
        p = MyProcess(10000)
        p.start()
        p.join()

    logger.info("main process end")
    close_log_queue()

執(zhí)行輸出大致如下所示:

$ tail logs/app.log 
2024-01-22 23:10:17 | INFO | mylogger | main.py:12 | run | pid: 7908, 1
2024-01-22 23:10:17 | INFO | mylogger | main.py:12 | run | pid: 7908, 2
2024-01-22 23:10:17 | INFO | mylogger | main.py:12 | run | pid: 7908, 3
2024-01-22 23:10:17 | INFO | mylogger | main.py:12 | run | pid: 7908, 4
2024-01-22 23:10:17 | INFO | mylogger | main.py:12 | run | pid: 7908, 5
2024-01-22 23:10:17 | INFO | mylogger | main.py:12 | run | pid: 7908, 6
2024-01-22 23:10:17 | INFO | mylogger | main.py:12 | run | pid: 7908, 7
2024-01-22 23:10:17 | INFO | mylogger | main.py:12 | run | pid: 7908, 8
2024-01-22 23:10:17 | INFO | mylogger | main.py:12 | run | pid: 7908, 9
2024-01-22 23:10:17 | INFO | mylogger | main.py:21 | <module> | main process end

補(bǔ)充

logging還內(nèi)置很多其它handler,比如按文件大小自動(dòng)切割,日志通過HTTP請求輸出,日志輸出到syslog等,可按照自己需求進(jìn)行定制。

到此這篇關(guān)于Python使用logging實(shí)現(xiàn)多進(jìn)程安全的日志模塊的文章就介紹到這了,更多相關(guān)Python多進(jìn)程安全的日志模塊內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python3基礎(chǔ)之基本數(shù)據(jù)類型概述

    Python3基礎(chǔ)之基本數(shù)據(jù)類型概述

    這篇文章主要介紹了Python3的基本數(shù)據(jù)類型,需要的朋友可以參考下
    2014-08-08
  • 詳解Python中的Descriptor描述符類

    詳解Python中的Descriptor描述符類

    這里我們將來詳解Python中的Descriptor描述符類,包括定義描述符并展示如何調(diào)用描述符,需要的朋友可以參考下
    2016-06-06
  • 詳解python爬蟲系列之初識爬蟲

    詳解python爬蟲系列之初識爬蟲

    這篇文章主要介紹了python爬蟲系列之初識爬蟲,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • Django框架ORM數(shù)據(jù)庫操作實(shí)例詳解

    Django框架ORM數(shù)據(jù)庫操作實(shí)例詳解

    這篇文章主要介紹了Django框架ORM數(shù)據(jù)庫操作,結(jié)合實(shí)例形式詳細(xì)分析了Django框架ORM數(shù)據(jù)庫基本增刪改查與相關(guān)函數(shù)使用技巧,需要的朋友可以參考下
    2019-11-11
  • python高手之路python處理excel文件(方法匯總)

    python高手之路python處理excel文件(方法匯總)

    用python來自動(dòng)生成excel數(shù)據(jù)文件。python處理excel文件主要是第三方模塊庫xlrd、xlwt、xluntils和pyExcelerator,除此之外,python處理excel還可以用win32com和openpyxl模塊
    2016-01-01
  • Django中URL的參數(shù)傳遞的實(shí)現(xiàn)

    Django中URL的參數(shù)傳遞的實(shí)現(xiàn)

    這篇文章主要介紹了Django中URL的參數(shù)傳遞的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • Python腳本開發(fā)中的命令行參數(shù)及傳參示例詳解

    Python腳本開發(fā)中的命令行參數(shù)及傳參示例詳解

    這篇文章主要為大家介紹了Python腳本開發(fā)中的命令行參數(shù)及傳參示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • Python用Pillow(PIL)進(jìn)行簡單的圖像操作方法

    Python用Pillow(PIL)進(jìn)行簡單的圖像操作方法

    下面小編就為大家?guī)硪黄狿ython用Pillow(PIL)進(jìn)行簡單的圖像操作方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-07-07
  • Python如何查看兩個(gè)數(shù)據(jù)庫的同名表的字段名差異

    Python如何查看兩個(gè)數(shù)據(jù)庫的同名表的字段名差異

    這篇文章主要介紹了Python如何查看兩個(gè)數(shù)據(jù)庫的同名表的字段名差異,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • 適合Python項(xiàng)目的五大SQL連接器

    適合Python項(xiàng)目的五大SQL連接器

    這篇文章,將要介紹當(dāng)前流行的、適合大多數(shù)Python程序員的、五大Python SQL數(shù)據(jù)庫連接器,并討論它們安裝和各種的優(yōu)缺點(diǎn)。需要的噴朋友可以參考下面文章的具體內(nèi)容
    2021-09-09

最新評論