Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Cara menggunakan perpustakaan log loguru dalam Python

Cara menggunakan perpustakaan log loguru dalam Python

王林
王林ke hadapan
2023-05-01 22:34:051973semak imbas

1. Gambaran Keseluruhan Pustaka log

dalam

pythonlogging agak seperti log4j untuk digunakan, tetapi konfigurasi biasanya lebih rumit dan tidak mudah untuk membina pelayan log. Penggantian pustaka standard logging ialah loguru, yang lebih mudah digunakan. loguru

Format output lalai ialah: masa, tahap, modul, nombor baris dan kandungan log. loguru Tidak perlu membuat loguru secara manual, ia boleh digunakan di luar kotak, yang lebih mudah digunakan daripada logger selain itu, output log mempunyai fungsi warna dan warna terbina dalam dan kawalan bukan warna adalah sangat mudah dan lebih mesra pengguna. logging

ialah perpustakaan bukan standard dan perlu dipasang terlebih dahulu Perintahnya ialah: **loguru****. **Selepas pemasangan, contoh penggunaan paling mudah adalah seperti berikut: pip3 install loguru

from loguru import logger

logger.debug('hello, this debug loguru')
logger.info('hello, this is info loguru')
logger.warning('hello, this is warning loguru')
logger.error('hello, this is error loguru')
logger.critical('hello, this is critical loguru')

Output kod di atas:

Cara menggunakan perpustakaan log loguru dalam Python

Penggunaan mencetak log ke fail juga sangat mudah, kod Seperti berikut:

from loguru import logger

logger.add('myloguru.log')

logger.debug('hello, this debug loguru')
logger.info('hello, this is info loguru')
logger.warning('hello, this is warning loguru')
logger.error('hello, this is error loguru')
logger.critical('hello, this is critical loguru')

Apabila kod di atas dijalankan, ia boleh dicetak ke konsol atau ke fail.

Cara menggunakan perpustakaan log loguru dalam Python

2. Penggunaan biasa

2.1. Format paparan

Format lalai ialah masa, tahap, nama + modul dan log Kandungan, di mana nama + modul berkod keras, ialah pembolehubah loguru bagi fail semasa Sebaiknya jangan ubah suai pembolehubah ini. __name__

Apabila projek menjadi lebih kompleks, menyesuaikan nama modul sangat berguna. Ia mudah untuk ditakrifkan dan diletakkan serta mengelak daripada terperangkap dalam butiran. Kami boleh menentukan nama modul secara manual melalui

. Seperti berikut: logger.configure

import sys

from loguru import logger

logger.configure(handlers=[
    {
        "sink": sys.stderr,
        "format": "{time:YYYY-MM-DD HH:mm:ss.SSS} |<lvl>{level:8}</>| {name} : {module}:{line:4} | <cyan>mymodule</> | - <lvl>{message}</>",
        "colorize": True
    },
])

logger.debug(&#39;this is debug&#39;)
logger.info(&#39;this is info&#39;)
logger.warning(&#39;this is warning&#39;)
logger.error(&#39;this is error&#39;)
logger.critical(&#39;this is critical&#39;)

: menunjukkan pemegang keluaran log atau destinasi, handlers menunjukkan output ke terminal baris arahan. sys.stderr

bermaksud output ke terminal "sink": sys.stderr

bermaksud pemformatan log. "format": bermaksud memaparkan warna mengikut tahap log. 8 bermakna lebar output ialah 8 aksara. <lvl>{level:8}></lvl>

"colorize":**: Menunjukkan warna paparan. True

Output kod di atas ialah:

Cara menggunakan perpustakaan log loguru dalam Python

Nama modul dikodkan keras di sini dan agak menyusahkan untuk sediakan setiap log dengan cara ini. Berikut menerangkan cara menentukan nama modul yang berbeza.

2.2. Menulis fail

Log secara amnya perlu diteruskan sebagai tambahan kepada terminal baris arahan, ia juga perlu ditulis ke fail. Pustaka log standard boleh mengkonfigurasi logger melalui fail konfigurasi, dan ia juga boleh dilaksanakan dalam kod, tetapi prosesnya agak rumit. Loguru adalah agak mudah Mari kita lihat bagaimana untuk melaksanakan fungsi ini dalam kod. Kod log adalah seperti berikut:

import sys

from loguru import logger

logger.configure(handlers=[
    {
        "sink": sys.stderr,
        "format": "{time:YYYY-MM-DD HH:mm:ss.SSS} |<lvl>{level:8}</>| {name} : {module}:{line:4} | <cyan>mymodule</> | - <lvl>{message}</>",
        "colorize": True
    },
    {
        "sink": &#39;first.log&#39;,
        "format": "{time:YYYY-MM-DD HH:mm:ss.SSS} |{level:8}| {name} : {module}:{line:4} | mymodule | - {message}",
        "colorize": False
    },
])

logger.debug(&#39;this is debug&#39;)
logger.info(&#39;this is info&#39;)
logger.warning(&#39;this is warning&#39;)
logger.error(&#39;this is error&#39;)
logger.critical(&#39;this is critical&#39;)

Satu-satunya perbezaan daripada 2.1 ialah

menambah logger.configure baharu dan menulisnya pada fail log. Penggunaannya sangat mudah. handler

Di atas hanya menetapkan format log melalui

, tetapi nama modul tidak berubah Dalam pembangunan projek sebenar, modul yang berbeza perlu menentukan nama modul yang berbeza semasa menulis log. Oleh itu, nama modul perlu diparameterkan untuk menjadikannya lebih praktikal. Kod sampel adalah seperti berikut: logger.configure

import sys

from loguru import logger

logger.configure(handlers=[
    {
        "sink": sys.stderr,
        "format": "{time:YYYY-MM-DD HH:mm:ss.SSS} |<lvl>{level:8}</>| {name} : {module}:{line:4} | <cyan>{extra[module_name]}</> | - <lvl>{message}</>",
        "colorize": True
    },
    {
        "sink": &#39;first.log&#39;,
        "format": "{time:YYYY-MM-DD HH:mm:ss.SSS} |{level:8}| {name} : {module}:{line:4} | {extra[module_name]} | - {message}",
        "colorize": False
    },
])

log = logger.bind(module_name=&#39;my-loguru&#39;)
log.debug("this is hello, module is my-loguru")

log2 = logger.bind(module_name=&#39;my-loguru2&#39;)
log2.info("this is hello, module is my-loguru2")

Parameterisasi logger.bind(module_name='my-loguru') dilaksanakan melalui kaedah bind. bind mengembalikan objek log di mana output log boleh dilakukan, supaya format log untuk modul berbeza boleh dilaksanakan. module_name

Fungsi menyesuaikan nama modul dalam loguru sedikit berbeza daripada perpustakaan pengelogan standard. Melalui kaedah bind, fungsi log standard

boleh dilaksanakan dengan mudah. Selain itu, log berstruktur boleh dilaksanakan dengan mudah melalui logging. bind和logger.configure

Output kod di atas adalah seperti berikut:

Cara menggunakan perpustakaan log loguru dalam Python

2.3.json log

Simpan dalam format json berstruktur Mudah, cuma tetapkan parameter loguru. Kodnya adalah seperti berikut: serialize=True

from loguru import logger

logger.add(&#39;json.log&#39;, serialize=True, encoding=&#39;utf-8&#39;)
logger.debug(&#39;this is debug message&#39;)
logger.info(&#39;this is info message&#39;)
logger.error(&#39;this is error message&#39;)

Kandungan output adalah seperti berikut:

Cara menggunakan perpustakaan log loguru dalam Python

2.4. Pembalut log

Fail log menyokong tiga tetapan: Gelung, simpan, mampat. Persediaan juga agak mudah. Terutamanya format mampatan sangat kaya dengan sokongan Format mampatan biasa disokong, seperti: loguru, "gz", "bz2", "xz", "lzma", "tar", "tar.gz", "tar.bz2" , "tar.xz". Kod sampel adalah seperti berikut: "zip"

from loguru import logger

logger.add("file_1.log", rotation="500 MB")  # 自动循环过大的文件
logger.add("file_2.log", rotation="12:00")  # 每天中午创建新文件
logger.add("file_3.log", rotation="1 week")  # 一旦文件太旧进行循环
logger.add("file_X.log", retention="10 days")  # 定期清理
logger.add("file_Y.log", compression="zip")  # 压缩节省空间

2.5.并发安全

loguru默认是线程安全的,但不是多进程安全的,如果使用了多进程安全,需要添加参数enqueue=True,样例代码如下:

logger.add("somefile.log", enqueue=True)

loguru另外还支持协程,有兴趣可以自行研究。

3.高级用法

3.1.接管标准日志logging

更换日志系统或者设计一套日志系统,比较难的是兼容现有的代码,尤其是第三方库,因为不能因为日志系统的切换,而要去修改这些库的代码,也没有必要。好在loguru可以方便的接管标准的日志系统。

样例代码如下:

import logging
import logging.handlers
import sys

from loguru import logger

handler = logging.handlers.SysLogHandler(address=(&#39;localhost&#39;, 514))
logger.add(handler)

class LoguruHandler(logging.Handler):
    def emit(self, record):
        try:
            level = logger.level(record.levelname).name
        except ValueError:
            level = record.levelno
        frame, depth = logging.currentframe(), 2
        while frame.f_code.co_filename == logging.__file__:
            frame = frame.f_back
            depth += 1
        logger.opt(depth=depth, exception=record.exc_info).log(level, record.getMessage())

logging.basicConfig(handlers=[LoguruHandler()], level=0, format=&#39;%(asctime)s %(filename)s %(levelname)s %(message)s&#39;,
                    datefmt=&#39;%Y-%M-%D %H:%M:%S&#39;)

logger.configure(handlers=[
    {
        "sink": sys.stderr,
        "format": "{time:YYYY-MM-DD HH:mm:ss.SSS} |<lvl>{level:8}</>| {name} : {module}:{line:4} | [ModuleA] | - <lvl>{message}</>",
        "colorize": True
    },
])

log = logging.getLogger(&#39;root&#39;)

# 使用标注日志系统输出
log.info(&#39;hello wrold, that is from logging&#39;)
log.debug(&#39;debug hello world, that is from logging&#39;)
log.error(&#39;error hello world, that is from logging&#39;)
log.warning(&#39;warning hello world, that is from logging&#39;)

# 使用loguru系统输出
logger.info(&#39;hello world, that is from loguru&#39;)

输出为:

Cara menggunakan perpustakaan log loguru dalam Python

3.2.输出日志到网络服务器

如果有需要,不同进程的日志,可以输出到同一个日志服务器上,便于日志的统一管理。我们可以利用自定义或者第三方库进行日志服务器和客户端的设置。下面介绍两种日志服务器的用法。

3.2.1.自定义日志服务器

日志客户端段代码如下:

# client.py
import pickle
import socket
import struct
import time

from loguru import logger

class SocketHandler:

    def __init__(self, host, port):
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.connect((host, port))

    def write(self, message):
        record = message.record
        data = pickle.dumps(record)
        slen = struct.pack(">L", len(data))
        self.sock.send(slen + data)

logger.configure(handlers=[{"sink": SocketHandler(&#39;localhost&#39;, 9999)}])

while True:
    time.sleep(1)
    logger.info("Sending info message from the client")
    logger.debug("Sending debug message from the client")
    logger.error("Sending error message from the client")

日志服务器代码如下:

# server.py
import pickle
import socketserver
import struct

from loguru import logger

class LoggingStreamHandler(socketserver.StreamRequestHandler):

    def handle(self):
        while True:
            chunk = self.connection.recv(4)
            if len(chunk) < 4:
                break
            slen = struct.unpack(&#39;>L&#39;, chunk)[0]
            chunk = self.connection.recv(slen)
            while len(chunk) < slen:
                chunk = chunk + self.connection.recv(slen - len(chunk))
            record = pickle.loads(chunk)
            level, message = record["level"].no, record["message"]
            logger.patch(lambda record: record.update(record)).log(level, message)

server = socketserver.TCPServer((&#39;localhost&#39;, 9999), LoggingStreamHandler)
server.serve_forever()

运行结果如下:

Cara menggunakan perpustakaan log loguru dalam Python

3.2.2.第三方库日志服务器

日志客户端代码如下:

# client.py
import zmq
from zmq.log.handlers import PUBHandler
from loguru import logger

socket = zmq.Context().socket(zmq.PUB)
socket.connect("tcp://127.0.0.1:12345")
handler = PUBHandler(socket)logger.add(handler)
logger.info("Logging from client")

日志服务器代码如下:

# server.py
import sys
import zmq
from loguru import logger

socket = zmq.Context().socket(zmq.SUB)
socket.bind("tcp://127.0.0.1:12345")
socket.subscribe("")
logger.configure(handlers=[{"sink": sys.stderr, "format": "{message}"}])

while True:
    _, message = socket.recv_multipart()
    logger.info(message.decode("utf8").strip())

3.3.与pytest结合

官方帮助中有一个讲解logurupytest结合的例子,讲得有点含糊不是很清楚。简单的来说,pytest有个fixture,可以捕捉被测方法中的logging日志打印,从而验证打印是否触发。

下面就详细讲述如何使用logurupytest结合的代码,如下:

import pytest
from _pytest.logging import LogCaptureFixture
from loguru import logger

def some_func(i, j):
    logger.info(&#39;Oh no!&#39;)
    logger.info(&#39;haha&#39;)
    return i + j

@pytest.fixture
def caplog(caplog: LogCaptureFixture):
    handler_id = logger.add(caplog.handler, format="{message}")
    yield caplog
    logger.remove(handler_id)

def test_some_func_logs_warning(caplog):
    assert some_func(-1, 3) == 2
    assert "Oh no!" in caplog.text

测试输出如下:

Cara menggunakan perpustakaan log loguru dalam Python

Atas ialah kandungan terperinci Cara menggunakan perpustakaan log loguru dalam Python. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam