1. Overview
The logging library in python
logging
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.
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.
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:php;toolbar:false;'>from loguru import logger
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;)</pre>
The above code output:
The usage of log printing to file is also very simple, the code As follows:
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')
When the above code is run, it can be printed to the console or to a file.
2. Common usage
2.1. Display format
loguruThe 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
. As follows: <pre class='brush:php;toolbar:false;'>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;)</pre>
handlers: indicates the log output handle or destination,
"sink": sys.stderrsys.stderr
indicates output to the command line terminal., means output to the terminal
"format":means log formatting.
"colorize":<lvl>{level:8}></lvl>
means displaying colors according to the log level. 8 means the output width is 8 characters.The output of the above code is:
True
**: Indicates the display color.
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": 'first.log', "format": "{time:YYYY-MM-DD HH:mm:ss.SSS} |{level:8}| {name} : {module}:{line:4} | mymodule | - {message}", "colorize": False }, ]) logger.debug('this is debug') logger.info('this is info') logger.warning('this is warning') logger.error('this is error') logger.critical('this is critical')The only difference from 2.1 is that
logger.configurelogger.configureadds a new
The above only sets the log format throughhandler
and writes it to the log file . Usage is very simple.
, 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:php;toolbar:false;'>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")</pre>
logger.bind(module_name='my-loguru')Parameterization of
loggingmodule_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
can be easily realized. Moreover, structured logging can be easily implemented through
The output of the above code is as follows:bind and logger.configure
.
2.3.json log
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:php;toolbar:false;'>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;)</pre>
The output content is as follows:
2.4. Log wrapping
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:php;toolbar:false;'>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") # 压缩节省空间</pre><h4 id="并发安全">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=('localhost', 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='%(asctime)s %(filename)s %(levelname)s %(message)s', datefmt='%Y-%M-%D %H:%M:%S') 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('root') # 使用标注日志系统输出 log.info('hello wrold, that is from logging') log.debug('debug hello world, that is from logging') log.error('error hello world, that is from logging') log.warning('warning hello world, that is from logging') # 使用loguru系统输出 logger.info('hello world, that is from loguru')
输出为:
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('localhost', 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('>L', 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(('localhost', 9999), LoggingStreamHandler) server.serve_forever()
运行结果如下:
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结合
官方帮助中有一个讲解loguru
与pytest
结合的例子,讲得有点含糊不是很清楚。简单的来说,pytest
有个fixture
,可以捕捉被测方法中的logging
日志打印,从而验证打印是否触发。
下面就详细讲述如何使用loguru
与pytest
结合的代码,如下:
import pytest from _pytest.logging import LogCaptureFixture from loguru import logger def some_func(i, j): logger.info('Oh no!') logger.info('haha') 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
测试输出如下:
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!

There are many methods to connect two lists in Python: 1. Use operators, which are simple but inefficient in large lists; 2. Use extend method, which is efficient but will modify the original list; 3. Use the = operator, which is both efficient and readable; 4. Use itertools.chain function, which is memory efficient but requires additional import; 5. Use list parsing, which is elegant but may be too complex. The selection method should be based on the code context and requirements.

There are many ways to merge Python lists: 1. Use operators, which are simple but not memory efficient for large lists; 2. Use extend method, which is efficient but will modify the original list; 3. Use itertools.chain, which is suitable for large data sets; 4. Use * operator, merge small to medium-sized lists in one line of code; 5. Use numpy.concatenate, which is suitable for large data sets and scenarios with high performance requirements; 6. Use append method, which is suitable for small lists but is inefficient. When selecting a method, you need to consider the list size and application scenarios.

Compiledlanguagesofferspeedandsecurity,whileinterpretedlanguagesprovideeaseofuseandportability.1)CompiledlanguageslikeC arefasterandsecurebuthavelongerdevelopmentcyclesandplatformdependency.2)InterpretedlanguageslikePythonareeasiertouseandmoreportab

In Python, a for loop is used to traverse iterable objects, and a while loop is used to perform operations repeatedly when the condition is satisfied. 1) For loop example: traverse the list and print the elements. 2) While loop example: guess the number game until you guess it right. Mastering cycle principles and optimization techniques can improve code efficiency and reliability.

To concatenate a list into a string, using the join() method in Python is the best choice. 1) Use the join() method to concatenate the list elements into a string, such as ''.join(my_list). 2) For a list containing numbers, convert map(str, numbers) into a string before concatenating. 3) You can use generator expressions for complex formatting, such as ','.join(f'({fruit})'forfruitinfruits). 4) When processing mixed data types, use map(str, mixed_list) to ensure that all elements can be converted into strings. 5) For large lists, use ''.join(large_li

Pythonusesahybridapproach,combiningcompilationtobytecodeandinterpretation.1)Codeiscompiledtoplatform-independentbytecode.2)BytecodeisinterpretedbythePythonVirtualMachine,enhancingefficiencyandportability.

ThekeydifferencesbetweenPython's"for"and"while"loopsare:1)"For"loopsareidealforiteratingoversequencesorknowniterations,while2)"while"loopsarebetterforcontinuinguntilaconditionismetwithoutpredefinediterations.Un

In Python, you can connect lists and manage duplicate elements through a variety of methods: 1) Use operators or extend() to retain all duplicate elements; 2) Convert to sets and then return to lists to remove all duplicate elements, but the original order will be lost; 3) Use loops or list comprehensions to combine sets to remove duplicate elements and maintain the original order.


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Atom editor mac version download
The most popular open source editor

SAP NetWeaver Server Adapter for Eclipse
Integrate Eclipse with SAP NetWeaver application server.

PhpStorm Mac version
The latest (2018.2.1) professional PHP integrated development tool

SublimeText3 Chinese version
Chinese version, very easy to use

SublimeText3 Linux new version
SublimeText3 Linux latest version
