Home  >  Article  >  Backend Development  >  How to use loguru log library in Python

How to use loguru log library in Python

王林
王林forward
2023-05-01 22:34:051972browse

1. Overview

The logging library in pythonlogging is a bit like log4j, but the configuration is usually more complicated. Building logs The server is not convenient either. The replacement for the standard library logging is loguru, which is much simpler to use.

loguru

The default output format is: time, level, module, line number and log content. loguru No need to manually create logger, it can be used out of the box, which is much easier to use than logging; in addition, the log output has built-in color functions, color and non-color The control is very convenient and more friendly.

loguru

is a non-standard library and needs to be installed in advance. The command is: **pip3 install loguru****. **After installation, the simplest usage example is as follows: <pre class="brush:py;">from loguru import logger logger.debug(&amp;#39;hello, this debug loguru&amp;#39;) logger.info(&amp;#39;hello, this is info loguru&amp;#39;) logger.warning(&amp;#39;hello, this is warning loguru&amp;#39;) logger.error(&amp;#39;hello, this is error loguru&amp;#39;) logger.critical(&amp;#39;hello, this is critical loguru&amp;#39;)</pre>The above code output:

How to use loguru log library in PythonThe usage of log printing to file is also very simple, the code As follows:

from loguru import logger

logger.add(&#39;myloguru.log&#39;)

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

When the above code is run, it can be printed to the console or to a file.

How to use loguru log library in Python2. Common usage

2.1. Display format

loguru

The default format is time, level, name Module and log content, the name module is hard-coded and is the __name__ variable of the current file. It is best not to modify this variable. When the project is more complex, it is very useful to customize the module name, which is easy to define and position and avoid getting bogged down in details. We can manually specify the module name through

logger.configure

. As follows: <pre class="brush:py;">import sys from loguru import logger logger.configure(handlers=[ { &quot;sink&quot;: sys.stderr, &quot;format&quot;: &quot;{time:YYYY-MM-DD HH:mm:ss.SSS} |&lt;lvl&gt;{level:8}&lt;/&gt;| {name} : {module}:{line:4} | &lt;cyan&gt;mymodule&lt;/&gt; | - &lt;lvl&gt;{message}&lt;/&gt;&quot;, &quot;colorize&quot;: True }, ]) logger.debug(&amp;#39;this is debug&amp;#39;) logger.info(&amp;#39;this is info&amp;#39;) logger.warning(&amp;#39;this is warning&amp;#39;) logger.error(&amp;#39;this is error&amp;#39;) logger.critical(&amp;#39;this is critical&amp;#39;)</pre>

handlers

: indicates the log output handle or destination, sys.stderr indicates output to the command line terminal.

"sink": sys.stderr

, means output to the terminal

"format":

means log formatting. <lvl>{level:8}></lvl> means displaying colors according to the log level. 8 means the output width is 8 characters.

"colorize":

True**: Indicates the display color.

The output of the above code is:

How to use loguru log library in Python

The module name is hard-coded here, and it is quite cumbersome to set up each log in this way. The following describes how to specify different module names.

2.2. Writing to files

Logs generally need to be persisted. In addition to outputting to the command line terminal, they also need to be written to files. The standard log library can configure the logger through the configuration file, and it can also be implemented in the code, but the process is relatively cumbersome. Loguru is relatively simple. Let's see how to implement this function in the code. The log code is as follows:

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;)

The only difference from 2.1 is that
logger.configure

adds a new handler and writes it to the log file . Usage is very simple.

The above only sets the log format through
logger.configure

, but the module name is not variable. In actual project development, different modules need to specify different module names when writing logs. Therefore, module names need to be parameterized to be more practical. The sample code is as follows: <pre class="brush:py;">import sys from loguru import logger logger.configure(handlers=[ { &quot;sink&quot;: sys.stderr, &quot;format&quot;: &quot;{time:YYYY-MM-DD HH:mm:ss.SSS} |&lt;lvl&gt;{level:8}&lt;/&gt;| {name} : {module}:{line:4} | &lt;cyan&gt;{extra[module_name]}&lt;/&gt; | - &lt;lvl&gt;{message}&lt;/&gt;&quot;, &quot;colorize&quot;: True }, { &quot;sink&quot;: &amp;#39;first.log&amp;#39;, &quot;format&quot;: &quot;{time:YYYY-MM-DD HH:mm:ss.SSS} |{level:8}| {name} : {module}:{line:4} | {extra[module_name]} | - {message}&quot;, &quot;colorize&quot;: False }, ]) log = logger.bind(module_name=&amp;#39;my-loguru&amp;#39;) log.debug(&quot;this is hello, module is my-loguru&quot;) log2 = logger.bind(module_name=&amp;#39;my-loguru2&amp;#39;) log2.info(&quot;this is hello, module is my-loguru2&quot;)</pre>

logger.bind(module_name='my-loguru')

Parameterization of module_name is realized through the bind method. bind returns a log object through which log output can be performed, so that log formats for different modules can be implemented. The function of customizing module names in loguru is a little different than the standard logging library. Through the bind method, the functions of standard log

logging

can be easily realized. Moreover, structured logging can be easily implemented through bind and logger.configure.

The output of the above code is as follows:

How to use loguru log library in Python2.3.json log

loguru

Save it as a structure Converting to json format is very simple, just set the serialize=True parameter. The code is as follows: <pre class="brush:py;">from loguru import logger logger.add(&amp;#39;json.log&amp;#39;, serialize=True, encoding=&amp;#39;utf-8&amp;#39;) logger.debug(&amp;#39;this is debug message&amp;#39;) logger.info(&amp;#39;this is info message&amp;#39;) logger.error(&amp;#39;this is error message&amp;#39;)</pre>The output content is as follows:

How to use loguru log library in Python2.4. Log wrapping

loguru

Log file support Three settings: loop, preserve, compress. The setup is also relatively simple. Especially the compression formats are very rich in support. Common compression formats are supported, such as: "gz", "bz2", "xz", "lzma", "tar", "tar.gz", "tar.bz2", "tar.xz" , "zip". The sample code is as follows: <pre class="brush:py;">from loguru import logger logger.add(&quot;file_1.log&quot;, rotation=&quot;500 MB&quot;) # 自动循环过大的文件 logger.add(&quot;file_2.log&quot;, rotation=&quot;12:00&quot;) # 每天中午创建新文件 logger.add(&quot;file_3.log&quot;, rotation=&quot;1 week&quot;) # 一旦文件太旧进行循环 logger.add(&quot;file_X.log&quot;, retention=&quot;10 days&quot;) # 定期清理 logger.add(&quot;file_Y.log&quot;, compression=&quot;zip&quot;) # 压缩节省空间</pre><h4>2.5.并发安全</h4> <p><code>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;)

输出为:

How to use loguru log library in 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()

运行结果如下:

How to use loguru log library in 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

测试输出如下:

How to use loguru log library in Python

The above is the detailed content of How to use loguru log library in Python. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete