一、介绍
loguru 是一个功能强大且易于使用的 Python 日志记录库。它提供了简单的语法和丰富的功能,使日志记录变得更加方便和灵活,而 logging 是一个通用且灵活的日志模块,适用于各种复杂的日志需求。可以根据项目的具体需求和个人偏好选择适合的日志库。在某些情况下,甚至可以同时使用 loguru 和 logging,以发挥它们各自的优势
官网:https://loguru.readthedocs.io/en/stable/overview.html
logging:python内置模块logging,日志模块
二、安装
pip install loguru
三、日志级别
- TRACE:最详细的日志级别,用于追踪代码的执行过程。
- DEBUG:用于调试目的的详细信息级别。
- INFO:提供程序运行过程中的一般信息。
- SUCCESS:表示成功的操作或事件。
- WARNING:表示可能的问题或警告。
- ERROR:表示错误情况,但不会导致程序终止。
- CRITICAL:表示严重错误,可能导致程序终止。
四、loguru.logger 记录器对象
- loguru.logger.add(sink,levelformat,filter,colorize,serialize, backtrace diagnose,enqueue, context,catch):用于向记录器添加处理程序,以将日志消息写入文件、终端或其他目标,返回 handler_id
- sink:可以传入一个 file 对象(file-like object),或一个 str 字符串或者 pathlib.Path 对象,或一个方法(coroutine function),或 logging 模块的 Handler(logging.Handler)。
- level:应将已记录消息发送到接收器的最低严重级别。
- format:格式化模块,在发送到接收器之前,使用模板对记录的消息进行格式化。
- filter:用于决定每个记录的消息是否应该发送到接收器。
- colorize:是否应将格式化消息中包含的颜色标记转换为用于终端着色的Ansi代码,或以其他方式剥离。如果None,根据水槽是否为TTY自动作出选择。
- serialize :在发送到接收器之前,记录的消息及其记录是否应该首先转换为JSON字符串。
- backtrace :格式化的异常跟踪是否应该向上扩展,超出捕获点,以显示生成错误的完整堆栈跟踪。
- diagnose :异常跟踪是否应该显示变量值以简化调试。在生产中,这应该设置为“False”,以避免泄漏敏感数据。
- enqueue :要记录的消息在到达接收器之前是否应该首先通过多进程安全队列。当通过多个进程将日志记录到文件中时,这是非常有用的。这还具有使日志调用非阻塞的优点。
- catch:是否应该自动捕获接收器处理日志消息时发生的错误。如果True上显示异常消息 sys.stderr。但是,异常不会传播到调用者,从而防止应用程序崩溃。
- rotation:分隔日志文件,何时关闭当前日志文件并启动一个新文件的条件,;例如,“500 MB”、“0.5 GB”、“1 month 2 weeks”、“10h”、“monthly”、“18:00”、“sunday”、“monday at 18:00”、“06:15”
- retention:可配置旧日志的最长保留时间,例如,“1 week, 3 days”、“2 months”
- compression :日志文件在关闭时应转换为的压缩或归档格式,例如,“gz”、“bz2”、“xz”、“lzma”、“tar”、“tar.gz”、“tar.bz2”、“tar.xz”、“zip”
- delay :是否应该在配置了接收器之后立即创建文件,或者延迟到第一个记录的消息。默认为" False "。
- mode:与内置open()函数一样的打开模式。默认为" “a”(以附加模式打开文件)。
- buffering :内置open()函数的缓冲策略,它默认为1(行缓冲文件)。
- encoding:文件编码与内置的" open() “函数相同。如果” None ",它默认为"locale.getpreferredencoding()
- context:指定附加的上下文信息。可以是字典或函数。如果是字典,则将其添加到每条日志消息的上下文中。如果是函数,则该函数将在记录每条消息时动态计算上下文信息。
- loguru.logger.log(leve,message): 记录日志消息。
- loguru.logger.debug(message): 记录调试级别的日志消息。
- loguru.logger.info(message): 记录信息级别的日志消息。
- loguru.logger.warning(message): 记录警告级别的日志消息。
- loguru.logger.error(message): 记录错误级别的日志消息。
- loguru.logger.critical(message): 记录严重错误级别的日志消息。
- loguru.logger.exception(message):记录异常信息
- loguru.logger.success(message):记录成功消息
- loguru.logger.trace(message):记录函数或代码块的跟踪信息
- loguru.logger.remove(handler_id):用于从记录器中移除指定的处理程序。handler_id 参数是要移除的处理程序的标识符
import loguru
handler_id = loguru.logger.add(sink='logs.log')
loguru.logger.info("用户操作")
loguru.logger.remove(id)
loguru.logger.info("用户操作1")
- loguru.logger.level(name,no,color,icon):自定义日志级别,name 参数是记录器的名称,可以是字符串或记录器对象,返回 level对象
- name:指定自定义日志级别的名称。这个名称将用于在日志消息中标识该级别。
- no:指定自定义日志级别的数值。数值越低,级别越高。确保自定义级别的数值与其他已定义的级别不重复。
- color:指定自定义日志级别的颜色。可以是一个字符串,表示颜色的名称或 RGB 值。例如,color=“green” 或 color=“#00FF00”。默认情况下,自定义级别没有颜色。
- icon:指定自定义日志级别的图标。可以是一个字符串,表示图标的 Unicode 字符。例如,icon=“❗”。默认情况下,自定义级别没有图标
import loguru
new_level = loguru.logger.level('CUSTOM', no=38, color='', icon='')
loguru.logger.log('CUSTOM', '自定义日志级别')
- loguru.logger.bind(**kwargs): 绑定关键字参数到记录器,使其在后续的日志消息中自动包含这些参数。返回loguru.logger对象
import loguru
loguru.logger.add('logs.log',format='{time:YYYY-MM-DD HH:MM:SS} | {level} | {extra[name]}:{message} ')
#logs.log 文件中会自动带上name,控制台上不会打印
extra_logger = loguru.logger.bind(name='张三')
extra_logger.info('用户操作')
extra_logger = loguru.logger.bind(name='李四')
extra_logger.info('用户操作')
- loguru.logger.complete():用于等待所有挂起的日志消息被处理完毕。它会阻塞当前线程,直到所有日志消息都被处理完成。
- loguru.logger.disable(name):用于禁用指定名称的记录器。name 参数是记录器的名称
- loguru.logger.enable(name):用于启用指定名称的记录器。name 参数是记录器的名称
- loguru.logger.configure(handlers, levels, extra, patcher, activation):用于配置 Loguru 记录器的行为
- handlers:指定要使用的日志处理程序。可以是单个处理程序对象或处理程序对象的列表。处理程序用于指定日志消息的输出方式,例如将日志消息写入文件、打印到控制台等。
- levels:指定日志级别的配置。可以是一个字典,用于指定不同处理程序的日志级别。键是处理程序的名称,值是日志级别的字符串表示,如 “DEBUG”、“INFO”、“WARNING”、“ERROR” 等。
- extra:指定额外的配置选项。可以是一个字典,用于指定其他配置选项。常见的选项包括 enqueue(是否启用异步日志记录)、rotation(日志文件的轮转方式)、retention(日志文件的保留策略)等。
- patcher:指定日志补丁程序。可以是一个函数,用于在配置日志记录器之前对日志记录器进行自定义补丁操作。该函数接受一个参数,即日志记录器对象,可以在函数中对其进行修改。
activation:指定是否激活日志记录器。默认为 True。如果设置为 False,则日志记录器将被禁用,不会记录任何日志消息。import loguru
import sys
# 对于脚本
config = {
'handlers': [
{'sink': sys.stdout},
{'sink': 'logs.log', 'format': '{time:YYYY-MM-DD HH:MM:SS.SSS} - {message}'},
],
'extra': {'user': 'someone'}
}
loguru.logger.configure(**config)
# 禁用库中的日志记录器
loguru.logger.disable('__name__')
loguru.logger.info('禁用')
# 启用库中的日志记录器
loguru.logger.enable('__name__')
loguru.logger.info('启用')
- loguru.logger.parse(file, pattern, cast, chunk):用于解析日志文件并返回相应的日志记录。
- file:参数是要解析的日志文件路径。
- pattern:参数是正则
- cast:参数是一个字典,用于指定将特定字段转换为特定类型的函数。
- chunk:参数是一个布尔值,指示是否将解析结果拆分为单独的记录。例如,loguru.logger.parse(“app.log”, pattern=“{time} {level} {message}”, cast={“time”: lambda t: datetime.strptime(t, “%Y-%m-%d %H:%M:%S”)}, chunk=True) 将解析名为 “app.log” 的日志文件,使用给定的格式模式和类型转换函数,并将结果拆分为单独的记录。
import loguru
# 格式format='{level.no}:{message}' 的日志
reg = r"(?P[0-9]+):(?P.*)"
caster = dict(lvl=int,msg=str)
for record in loguru.logger.parse("logs.log",pattern=reg,cast=caster):
print(record)
- loguru.logger.opt(exception,record,lazy,colors,depth,ansi): 创建一个新的记录器对象,可以对该对象进行特定的配置。返回loguru.logger对象,在生产环境中记录详细信息,而又不希望降低性能,可以使用 opt()
- loguru.logger.patch(patcher):用于对记录器进行补丁,以添加或修改其行为。patcher 参数是一个函数,接受一个记录器对象作为参数,并在其上进行修改。返回loguru.logger对象
import loguru
import time
loguru.logger.add('logs.log', format="{extra[time]} {message}")
def patch_fun(record):
record["extra"].update(time=time.time())
logger = loguru.logger.patch(patch_fun)
logger.info('修改')
- loguru.logger.catch(exception,level,reraise, onerror,exclude, default, message): 捕获异常并记录为错误级别的日志消息,异常追溯,可以作为装饰器使用
- exception:指定要捕获的异常类型。可以是单个异常类型或异常类型的元组。例如,exception=ValueError 将只捕获 ValueError 类型的异常。
- level:指定记录的日志级别。默认为 “ERROR”。可以是日志级别的字符串表示,如 “DEBUG”、“INFO”、“WARNING”、“ERROR” 等。
- reraise:指定是否重新引发捕获的异常。默认为 False。如果设置为 True,则在记录异常后将重新引发该异常,以便在上层代码中继续处理。
- onerror:指定异常处理函数。可以是自定义的函数,接受捕获的异常对象作为参数,并返回一个布尔值来指示是否应该处理该异常。如果返回 True,则处理该异常;如果返回 False,则不处理该异常。
- exclude:指定要排除的异常类型。可以是单个异常类型或异常类型的元组。例如,exclude=(ValueError, TypeError) 将排除 ValueError 和 TypeError 类型的异常。
- default:指定默认返回值。如果设置了 default,并且捕获的异常与 exception 参数中指定的异常类型不匹配,将返回 default 值。
- message:指定记录的日志消息。可以是字符串或格式化字符串。可以使用占位符 {exception} 来插入捕获的异常的字符串表示形式。
import loguru
loguru.logger.add('logs_{time}.log')
@loguru.logger.catch
def my_function(x, y, z):
return 1 / (x + y + z)
if __name__ == '__main__':
my_function(1,2)
import loguru
loguru.logger.add('logs_{time}.log')
def my_function(x, y, z):
return 1 / (x + y + z)
if __name__ == '__main__':
with loguru.logger.catch(message='错误'):
my_function(1,2)
- loguru.logger.contextualize():用于创建一个新的上下文记录器,该记录器继承了当前记录器的配置和处理程序。通过调用loguru.logger.contextualize(),可以在不影响全局记录器的情况下对特定上下文中的日志进行配置和处理
import loguru
logger = loguru.logger.bind(name='张三')
logger.add('logs.log', format="{message} | {extra[name]} {extra}")
with loguru.logger.contextualize(sex='男'):
logger.info("新的上下文记录器")
logger.info("Done.")
五、loguru.logger 占位符
- {time}:日志消息的时间戳,格式为 YYYY-MM-DD HH:MM:SS.SSS。
- {time:YYYY-MM-DD HH:MM:SS}:自定义格式的时间戳。您可以根据需要指定日期和时间的格式。
- {time:YYYY-MM-DD}:仅显示日期部分的时间戳。
- {time:HH:MM:SS}:仅显示时间部分的时间戳。
- {level}:日志消息的级别。
- {level.name}:日志级别的名称(例如,INFO、WARNING、ERROR)。
- {level.no}:日志级别的数字代码(例如,20、30、40)。
- {level.icon}:表示日志级别的图标。
- {file}:包含日志消息的源代码文件名。
- {line}:包含日志消息的源代码文件中的行号。
- {function}:包含日志消息的函数或方法名。
- {module}:包含日志消息的模块名。
- {name}:记录器的名称。
- {message}:日志消息的内容。
- {thread.name}:当前线程的名称。
- {process.name}:当前进程的名称。
- {exception}:如果日志消息是由异常引发的,将包含异常的详细信息。
- {elapsed}:从应用程序启动到记录日志消息的时间间隔。
- {elapsed.total}:从应用程序启动到现在的总时间间隔。
- {elapsed.diff}:从上一个日志消息到现在的时间间隔
- {extra}:用户绑定的属性字典(参见bind())
六、案例
- 打印控制台并写入文件
import loguru
#level设置级别,rotation超过文件大小重新生成文件
loguru.logger.add('logs_{time}.log',level='TRACE',rotation='100KB')
for _ in range(1000):
loguru.logger.debug('debug1')
loguru.logger.info('debug2')
loguru.logger.warning('debug3')
loguru.logger.error('debug4')
loguru.logger.critical('debug5')
loguru.logger.exception('debug6')
loguru.logger.success('debug7')
loguru.logger.trace('debug8')
- 不打印到控制台只写入文件
import loguru
loguru.logger.remove(handler_id=None)
#level设置级别,rotation超过文件大小重新生成文件
loguru.logger.add('logs_{time}.log',level='TRACE',rotation='100KB')
for _ in range(1000):
loguru.logger.debug('debug1')
loguru.logger.info('debug2')
loguru.logger.warning('debug3')
loguru.logger.error('debug4')
loguru.logger.critical('debug5')
loguru.logger.exception('debug6')
loguru.logger.success('debug7')
loguru.logger.trace('debug8')
- 设置过滤规则
import loguru
#logs_{time}.log文件只会写入ERROR级别的日志
def error_filter(record):
return record["level"].name == "ERROR"
#level设置级别,rotation超过文件大小重新生成文件
loguru.logger.add('logs_{time}.log',filter=error_filter)
loguru.logger.debug('debug1')
loguru.logger.info('debug2')
loguru.logger.warning('debug3')
loguru.logger.error('debug4')
loguru.logger.critical('debug5')
loguru.logger.exception('debug6')
loguru.logger.success('debug7')
loguru.logger.trace('debug8')
- 异常追溯
import loguru
loguru.logger.add('logs_{time}.log')
@loguru.logger.catch
def my_function(x, y, z):
return 1 / (x + y + z)
if __name__ == '__main__':
my_function(1,2)
import loguru
loguru.logger.add('logs_{time}.log')
def my_function(x, y, z):
return 1 / (x + y + z)
if __name__ == '__main__':
try:
my_function(1,2)
except Exception as e:
loguru.logger.exception('异常追溯')
import loguru
loguru.logger.add('logs_{time}.log')
def my_function(x, y, z):
return 1 / (x + y + z)
if __name__ == '__main__':
with loguru.logger.catch(message='错误'):
my_function(1,2)
- 使用logging模块处理器
import loguru
import logging
stream_handler = logging.StreamHandler()
loguru.logger.add(stream_handler, format="{message}")
loguru.logger.info('test')