成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

為什么不推薦使用Python原生日志庫?

開發 前端
Python自帶的logging我個人不推介使用,不太Pythonic,而開源的Loguru庫成為眾多工程師及項目中首選,本期將同時對logging及Loguru進行使用對比,希望有所幫助。

包括我在內的大多數人,當編寫小型腳本時,習慣使用print來debug,肥腸方便,這沒問題,但隨著代碼不斷完善,日志功能一定是不可或缺的,極大程度方便問題溯源以及甩鍋,也是每個工程師必備技能。

Python自帶的logging我個人不推介使用,不太Pythonic,而開源的Loguru庫成為眾多工程師及項目中首選,本期將同時對logging及Loguru進行使用對比,希望有所幫助。

快速示例

在logging中,默認的日志功能輸出的信息較為有限:

import logging

logger = logging.getLogger(__name__)

def main():
    logger.debug("This is a debug message")
    logger.info("This is an info message")
    logger.warning("This is a warning message")
    logger.error("This is an error message")

if __name__ == "__main__":
    main()

輸出(logging默認日志等級為warning,故此處未輸出info與debug等級的信息):

WARNING:root:This is a warning message
ERROR:root:This is an error message

再來看看loguru,默認生成的信息就較為豐富了:

from loguru import logger

def main():
    logger.debug("This is a debug message")
    logger.info("This is an info message")
    logger.warning("This is a warning message")
    logger.error("This is an error message")

if __name__ == "__main__":
    main()

提供了執行時間、等級、在哪個函數調用、具體哪一行等信息。

格式化日志

格式化日志允許我們向日志添加有用的信息,例如時間戳、日志級別、模塊名稱、函數名稱和行號。

在logging中使用%達到格式化目的:

import logging

# Create a logger and set the logging level
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s | %(levelname)s | %(module)s:%(funcName)s:%(lineno)d - %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S",
)

logger = logging.getLogger(__name__)

def main():
    logger.debug("This is a debug message")
    logger.info("This is an info message")
    logger.warning("This is a warning message")
    logger.error("This is an error message")

輸出:

2023-10-18 15:47:30 | INFO | tmp:<module>:186 - This is an info message
2023-10-18 15:47:30 | WARNING | tmp:<module>:187 - This is a warning message
2023-10-18 15:47:30 | ERROR | tmp:<module>:188 - This is an error message

而loguru使用和f-string相同的{}格式,更方便:

from loguru import logger

logger.add(
    sys.stdout,
    level="INFO",
    format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {module}:{function}:{line} - {message}",
)

日志保存

在logging中,實現日志保存與日志打印需要兩個額外的類,FileHandler 和 StreamHandler:

import logging

logging.basicConfig(
    level=logging.DEBUG,
    format="%(asctime)s | %(levelname)s | %(module)s:%(funcName)s:%(lineno)d - %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S",
    handlers=[
        logging.FileHandler(filename="/your/save/path/info.log", level=logging.INFO),
        logging.StreamHandler(level=logging.DEBUG),
    ],
)

logger = logging.getLogger(__name__)

def main():
    logging.debug("This is a debug message")
    logging.info("This is an info message")
    logging.warning("This is a warning message")
    logging.error("This is an error message")


if __name__ == "__main__":
    main()

但是在loguru中,只需要使用add方法即可達到目的:

from loguru import logger

logger.add(
    'info.log',
    format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {module}:{function}:{line} - {message}",
    level="INFO",
)


def main():
    logger.debug("This is a debug message")
    logger.info("This is an info message")
    logger.warning("This is a warning message")
    logger.error("This is an error message")


if __name__ == "__main__":
    main()

日志輪換

日志輪換指通過定期創建新的日志文件并歸檔或刪除舊的日志來防止日志變得過大。

在logging中,需要一個名為 TimedRotatingFileHandler 的附加類,以下代碼示例代表每周切換到一個新的日志文件 ( when=“WO”, interval=1 ),并保留最多 4 周的日志文件 ( backupCount=4 ):

import logging
from logging.handlers import TimedRotatingFileHandler

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

# Create a formatter with the desired log format
formatter = logging.Formatter(
    "%(asctime)s | %(levelname)-8s | %(module)s:%(funcName)s:%(lineno)d - %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S",
)

file_handler = TimedRotatingFileHandler(
    filename="debug2.log", when="WO", interval=1, backupCount=4
)
file_handler.setLevel(logging.INFO)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)


def main():
    logger.debug("This is a debug message")
    logger.info("This is an info message")
    logger.warning("This is a warning message")
    logger.error("This is an error message")


if __name__ == "__main__":
    main()

在loguru中,可以通過將 rotation 和 retention 參數添加到 add 方法來達到目的,如下示例,同樣肥腸方便:

from loguru import logger

logger.add("debug.log", level="INFO", rotation="1 week", retention="4 weeks")


def main():
    logger.debug("This is a debug message")
    logger.info("This is an info message")
    logger.warning("This is a warning message")
    logger.error("This is an error message")


if __name__ == "__main__":
    main()

日志篩選

日志篩選指根據特定條件有選擇的控制應輸出與保存哪些日志信息。

在logging中,實現該功能需要創建自定義日志過濾器類:

import logging


logging.basicConfig(
    filename="test.log",
    format="%(asctime)s | %(levelname)-8s | %(module)s:%(funcName)s:%(lineno)d - %(message)s",
    level=logging.INFO,
)


class CustomFilter(logging.Filter):
    def filter(self, record):
        return "Cai Xukong" in record.msg


# Create a custom logging filter
custom_filter = CustomFilter()

# Get the root logger and add the custom filter to it
logger = logging.getLogger()
logger.addFilter(custom_filter)


def main():
    logger.info("Hello Cai Xukong")
    logger.info("Bye Cai Xukong")


if __name__ == "__main__":
    main()

在loguru中,可以簡單地使用lambda函數來過濾日志:

from loguru import logger

logger.add("test.log", filter=lambda x: "Cai Xukong" in x["message"], level="INFO")


def main():
    logger.info("Hello Cai Xukong")
    logger.info("Bye Cai Xukong")


if __name__ == "__main__":
    main()

捕獲異常

在logging中捕獲異常較為不便且難以調試,如:

import logging

logging.basicConfig(
    level=logging.DEBUG,
    format="%(asctime)s | %(levelname)s | %(module)s:%(funcName)s:%(lineno)d - %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S",
)


def division(a, b):
    return a / b


def nested(c):
    try:
        division(1, c)
    except ZeroDivisionError:
        logging.exception("ZeroDivisionError")


if __name__ == "__main__":
    nested(0)
Traceback (most recent call last):
  File "logging_example.py", line 16, in nested
    division(1, c)
  File "logging_example.py", line 11, in division
    return a / b
ZeroDivisionError: division by zero

上面輸出的信息未提供觸發異常的c值信息,而在loguru中,通過顯示包含變量值的完整堆棧跟蹤來方便用戶識別:

Traceback (most recent call last):
  File "logging_example.py", line 16, in nested
    division(1, c)
  File "logging_example.py", line 11, in division
    return a / b
ZeroDivisionError: division by zero

值得一提的是,loguru中的catch裝飾器允許用戶捕獲函數內任何錯誤,且還會標識發生錯誤的線程:

from loguru import logger


def division(a, b):
    return a / b


@logger.catch
def nested(c):
    division(1, c)


if __name__ == "__main__":
    nested(0)

OK,作為普通玩家以上功能足以滿足日常日志需求,通過對比logging與loguru應該讓大家有了直觀感受,哦對了,loguru如何安裝?

pip install loguru

以上就是本期的全部內容,期待點贊在看,我是啥都生,下次再見。

責任編輯:趙寧寧 來源: 啥都會一點的研究生
相關推薦

2024-11-29 08:20:22

Autowired場景項目

2024-06-04 00:10:00

開發拷貝

2024-11-12 10:30:54

Docker部署數據庫

2018-11-29 14:30:42

數據庫外鍵約束應用程序

2024-09-12 08:32:42

2025-05-16 02:00:00

HashMapJava代碼

2021-08-23 13:02:50

MySQLJOIN數據庫

2022-01-11 10:29:32

Docker文件掛載

2025-04-29 07:06:20

2021-07-04 14:19:03

RabbitMQ消息轉換

2021-01-13 09:55:29

try-catch-fJava代碼

2020-08-31 11:20:53

MySQLuuidid

2024-03-11 11:02:03

Date類JavaAPI

2020-07-02 14:12:52

C++語言編程

2023-09-27 23:03:01

Java虛擬線程

2024-07-29 09:03:00

2020-02-25 17:04:05

數據庫云原生分布式

2020-06-18 10:21:46

Python程序員技術

2022-12-26 00:00:03

非繼承關系JDK

2023-10-09 18:39:13

Python代碼
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久综合99 | 一区二区精品在线 | 亚洲国产一区二区三区四区 | 在线色| 99久久精品国产一区二区三区 | 国产日韩欧美在线 | 精品视频一二区 | 少妇性l交大片免费一 | 日韩中文字幕在线 | 日韩av免费看 | 99精品免费久久久久久日本 | 中文字幕在线观看一区二区 | 国产精品毛片 | 亚洲国产精品一区二区久久 | 日韩中文字幕免费在线观看 | 亚洲a一区二区 | 亚洲在线日韩 | 成年人在线播放 | 国产久| 国产精品日韩欧美一区二区三区 | 一级黄色片网址 | 久久精品久久久 | 欧美11一13sex性hd | 免费观看www7722午夜电影 | 在线视频 中文字幕 | 羞羞网站免费 | 久久中文字幕一区 | 久草在线在线精品观看 | 有码在线 | www.久| 日韩成人国产 | 日韩不卡视频在线 | 精久久久 | 亚洲国产一区在线 | 国产99精品 | 台湾a级理论片在线观看 | 中文字幕第十一页 | 一级做a| 91久久久久久久久久久久久 | 亚洲风情在线观看 | 污视频免费在线观看 |