文章目录
🚀一、了解日志
日志是记录了一系列事件或活动的文件。在计算机领域,它通常用于记录程序或系统的运行状况和维护信息,以便在需要时进行故障排除或回溯。通过分析日志文件,管理员可以了解系统的使用情况、问题发生的原因以及如何解决这些问题。
日志通常包含时间戳、事件描述、错误消息、警报等信息。它们可以按照不同的标准来分类和过滤,例如按照事件类型、日志级别、时间戳范围等。常见的日志类型包括系统日志、安全日志、应用程序日志等。
🌈二、日志作用
调试和故障排除:通过分析日志文件可以了解系统崩溃或出现异常的原因,进而进行修复和调试。
性能调优:通过记录系统性能指标和资源利用情况等信息,管理员可以了解系统的瓶颈所在,从而进行针对性的优化。
安全审计:日志可以记录系统的安全事件、访问控制和行为审计等信息,以便于发现并防止潜在的安全问题。
统计分析:管理员可以通过日志记录用户行为、系统使用情况、网络流量等信息进行统计分析,以便于优化服务和提高用户满意度。
🌈三、了解日志模块
logging 模块提供了一种灵活且易于使用的方式来记录应用程序的状态和调试信息。它允许将消息分发到多个处理程序(handlers),并支持不同级别的日志消息。 logging模块是Python内置的标准模块,主要用于输出运行日志,可以设置输出日志的等级、日志保存路径、日志文件回滚等;
⭐四、日志级别
在 logging 模块中,日志级别用于描述日志的重要程度。它们按照严重程度分为以下五个级别: DEBUG:最详细的日志信息,通常只在调试问题时使用; INFO:确认一切按预期运行; WARNING:表示发生了一些意外或异常情况,但是该软件还可以正常运行; ERROR:由于更严重的问题,软件已无法执行某些功能; CRITICAL:严重错误,表明程序本身可能无法继续运行。
默认情况下,logging 组件会关闭低级别的日志消息并仅记录 WARNING 级别及其以上的消息。如果需要记录更多详细信息,则需要将 Logger 的 level 属性设置为其他级别。
# DEBUG # 最详细的调试信息,通常只在开发阶段使用。通过记录变量值、函数参数、分支走向等信息帮助调试人员解决问题。
# INFO # INFO 级别的日志通常用于确认系统正在按预期运行。例如,记录请求的处理时间、数据库操作数量、任务的完成状态等。
# WARNING # WARNING 级别的日志表示出现了一些意外或异常情况,但是该软件还可以正常运行。例如,数据缺失或配置文件格式错误等。
# ERROR # ERROR 级别的日志表示由于更严重的问题,软件已无法执行某些功能。例如,数据库连接失败、文件无法打开等错误。
# CRITICAL # 最高级别的日志级别,用于记录严重错误,表明程序本身可能无法继续运行。例如,内存耗尽、服务器崩溃等。
在应用程序中,通常会使用多个不同的日志级别来记录不同类型的事件。这使得开发人员可以快速识别和排除问题,并加快故障排除的过程。
# 开发应用程序或部署开发环境时, # 可以使用DEBUG或INFO级别的日志获取尽可能详细的日志信息来进行开发或部署调试; # # # # 应用上线或部署生产环境时,应该使用WARNING或ERROR或CRITICAL级别的日志来降低机器的I/O压力和提高获取错误日志信息的效率。 # 日志级别的指定通常都是在应用程序的配置文件中进行指定的。 # # # # 说明: # # -上面列表中的日志等级是从上到下依次升高的, # 即:DEBUG < INFO < WARNING < ERROR < CRITICAL, # 而日志的信息量是依次减少的; # # -当为某个应用程序指定一个日志级别后, # 应用程序会记录所有日志级别大于或等于指定日志级别的日志信息, # 而不是仅仅记录指定级别的日志信息, # nginx、php等应用程序以及这里的python的logging模块都是这样的。 # 同样,logging模块也可以指定日志记录器的日志级别, # 只有级别大于或等于该指定日志级别的日志记录才会被输出,小于该等级的日志记录将会被丢弃。
💥五、记录日志-基础
logging.getLogger(name=None) 是 logging 模块中的一个重要函数,用于创建并返回一个 logger 对象。这个函数可以接受一个字符串作为参数,该字符串表示要创建的 logger 的名称。如果未提供名称,则会创建一个名为 root 的默认 logger。
import logging # 创建一个 logger logger = logging.getLogger('my_logger') logger.setLevel(logging.INFO) # 将 StreamHandler 添加到 logger 中 --- StreamHandler处理器:将日志消息输出到标准输出或标准错误流。 logger.addHandler(logging.StreamHandler()) # 记录一条日志消息 logger.info('This is an info message')
logging 模块定义了五个日志级别(从低到高):DEBUG、INFO、WARNING、ERROR 和 CRITICAL。默认情况下,只有 WARNING 以及更高级别的日志消息才会被记录。可以通过设置 Logger 的日志级别来控制哪些消息应该被记录。
logger.setLevel(logging.DEBUG) # 记录所有级别的日志消息
import logging # 创建一个 logger logger = logging.getLogger('my_logger') # 设置日志级别 logger.setLevel(logging.DEBUG) # 将 StreamHandler 添加到 logger 中 --- StreamHandler处理器:将日志消息输出到标准输出或标准错误流。 logger.addHandler(logging.StreamHandler()) # 发布日志消息 logger.debug('This is a debug message') # 创建了一个名为 'my_logger' 的 logger,设置其日志级别为 DEBUG,并发布了一条 DEBUG 级别的日志消息。
logging模块定义的模块级别的常用函数
函数 | 说明 |
---|---|
logging.debug(msg, *args, **kwargs) | 创建一条严重级别为DEBUG的日志记录 |
logging.info(msg, *args, **kwargs) | 创建一条严重级别为INFO的日志记录 |
logging.warning(msg, *args, **kwargs) | 创建一条严重级别为WARNING的日志记录 |
logging.error(msg, *args, **kwargs) | 创建一条严重级别为ERROR的日志记录 |
logging.critical(msg, *args, **kwargs) | 创建一条严重级别为CRITICAL的日志记录 |
logging.log(level, *args, **kwargs) | 创建一条严重级别为level的日志记录 |
logging.basicConfig(**kwargs) | 对root logger进行一次性配置 |
""" logging.log() 函数的参数说明: level:指定要记录的日志级别,可选的取值有 DEBUG、INFO、WARNING、ERROR、CRITICAL。 *args:需要记录的一个或多个日志消息(字符串)。 **kwargs:可选参数,包括 extra、exc_info、stack_info、etc. """ import logging # 创建一个 logger logger = logging.getLogger('my_logger') # 设置日志级别 logger.setLevel(logging.DEBUG) # 将 StreamHandler 添加到 logger 中 --- StreamHandler处理器:将日志消息输出到标准输出或标准错误流。 # logger.addHandler(logging.StreamHandler()) # 将一条消息记录到日志文件或控制台 logging.log(logging.INFO, 'This is an info message')
❤️六、记录日志-处理器handler
在 logging 模块中,处理器(handler)是一种组件,可以将日志记录到不同的位置,例如输出到文件、发送到电子邮件、发布至网络等等。每个 logger 可以拥有零个或多个 handler,用于控制将记录哪些消息到哪个位置。
logging 模块支持多种类型的处理器
# StreamHandler:将日志消息输出到标准输出或标准错误流。 # # FileHandler:将日志消息输出到指定的文件中。 # # RotatingFileHandler:类似于 FileHandler,但它可以自动轮换多个日志文件,以避免一个文件太大而无法存储问题。 # # SMTPHandler:向指定的邮件地址发送日志消息。 # # SysLogHandler:向系统日志服务(syslog)输出日志消息。 # # NTEventLogHandler:向 Windows 事件日志输出日志消息。
import logging # 创建一个 logger logger = logging.getLogger('my_logger') logger.setLevel(logging.INFO) # 创建一个 StreamHandler 并设置日志级别为 INFO console_handler = logging.StreamHandler() console_handler.setLevel(logging.INFO) # 将 StreamHandler 添加到 logger 中 logger.addHandler(console_handler) # 记录一条日志消息 logger.info('This is an info message') # 首先创建了名为 'my_logger' 的 logger 对象,将其日志级别设置为 INFO。 # 然后,创建了一个名为 console_handler 的 StreamHandler 并将它的日志级别设置为 INFO。 # 最后,将 handler 添加到 logger 中,并通过 logger.info() 方法发布一条 INFO 级别的日志消息。
使用处理器 handler 可以扩展 logging 模块的功能并将日志记录到不同的位置,这对于应用程序的运行时跟踪或调试非常有用。
🎬七、记录日志-格式化记录
在 logging 模块中,格式化记录(Formatted log record)是一种将日志消息格式化为字符串的方式,以便于输出和阅读。可以使用 Formatter 类来创建自定义的格式化记录,以满足特定应用程序需求。
logging模块中定义好的可以用于format格式字符串说明
字段/属性名称 | 使用格式 | 描述 |
---|---|---|
asctime | %(asctime)s | 将日志的时间构造成可读的形式,默认情况下是‘2016-02-08 12:00:00,123’精确到毫秒 |
name | %(name)s | 所使用的日志器名称,默认是’root’,因为默认使用的是 rootLogger |
filename | %(filename)s | 调用日志输出函数的模块的文件名; pathname的文件名部分,包含文件后缀 |
funcName | %(funcName)s | 由哪个function发出的log, 调用日志输出函数的函数名 |
levelname | %(levelname)s | 日志的最终等级(被filter修改后的) |
message | %(message)s | 日志信息, 日志记录的文本内容 |
lineno | %(lineno)d | 当前日志的行号, 调用日志输出函数的语句所在的代码行 |
levelno | %(levelno)s | 该日志记录的数字形式的日志级别(10, 20, 30, 40, 50) |
pathname | %(pathname)s | 完整路径 ,调用日志输出函数的模块的完整路径名,可能没有 |
process | %(process)s | 当前进程, 进程ID。可能没有 |
processName | %(processName)s | 进程名称,Python 3.1新增 |
thread | %(thread)s | 当前线程, 线程ID。可能没有 |
threadName | %(thread)s | 线程名称 |
module | %(module)s | 调用日志输出函数的模块名, filename的名称部分,不包含后缀即不包含文件后缀的文件名 |
created | %(created)f | 当前时间,用UNIX标准的表示时间的浮点数表示; 日志事件发生的时间–时间戳,就是当时调用time.time()函数返回的值 |
relativeCreated | %(relativeCreated)d | 输出日志信息时的,自Logger创建以 来的毫秒数; 日志事件发生的时间相对于logging模块加载时间的相对毫秒数 |
msecs | %(msecs)d | 日志事件发生事件的毫秒部分。logging.basicConfig()中用了参数datefmt,将会去掉asctime中产生的毫秒部分,可以用这个加上 |
import logging # 创建一个 logger 对象,并设置其日志级别为 INFO logger = logging.getLogger('my_logger') logger.setLevel(logging.INFO) # 创建一个 FileHandler,将日志记录到文件 'example.log' 中 fh = logging.FileHandler('example.log') # 将 FileHandler 添加到 logger 中 logger.addHandler(fh) # 创建一个 Formatter 对象并设置日志消息的格式 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') fh.setFormatter(formatter) # 记录一条 INFO 级别的日志消息 logger.info('This is an info message') # 创建了名为 'my_logger' 的 logger 对象,并将其日志级别设为 INFO。接着,创建了一个 FileHandler 对象并将其添加到 logger 对象中。然后,通过 Formatter 类创建了一个格式化记录对象 formatter,并将其设置为日志消息的格式。最后,将 formatter 对象添加到 FileHandler 对象中,以便对每条日志消息进行格式化处理。 # 当调用 logger.info() 方法写入日志消息时,该消息会被传递给已经设置了格式化记录的 FileHandler 对象并格式化为指定的字符串格式。例如,如果设置了 '%(asctime)s - %(name)s - %(levelname)s - %(message)s' 的格式化字符串,则会在每条日志消息中输出时间戳、logger 对象的名称、日志级别和消息内容。
import logging # 创建一个 logger 对象,并设置其日志级别为 INFO logger = logging.getLogger('my_logger') logger.setLevel(logging.INFO) # 创建一个 FileHandler,用于将日志记录到文件 'example.log' 中 fh = logging.FileHandler('example.log') # 设置 FileHandler 的日志级别为 DEBUG fh.setLevel(logging.DEBUG) # 创建一个 Formatter 对象,用于设置日志消息的格式 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') # 将 Formatter 对象添加到 FileHandler 中 fh.setFormatter(formatter) # 将 FileHandler 添加到 logger 对象中 logger.addHandler(fh) # 记录一条 INFO 级别的日志消息 logger.info('This is an info message') # 记录一条 DEBUG 级别的日志消息 logger.debug('This is a debug message') # 首先创建了名为 'my_logger' 的 logger 对象,并设置其日志级别为 INFO。接着,创建了一个 FileHandler 对象,并指定要将日志记录到文件 'example.log' 中。然后,将 FileHandler 的日志级别设置为 DEBUG,并创建一个 Formatter 对象,以控制日志消息的格式。最后,将 Formatter 对象和 FileHandler 对象添加到 logger 中。 # 在 logger 对象准备就绪后,可以通过调用 logger.info() 和 logger.debug() 方法发布不同级别的日志消息。这些消息将分别记录在 'example.log' 文件中,其中 INFO 级别的消息包含时间戳、logger 名称、日志级别和消息内容等信息,而 DEBUG 级别的消息则包含更多的细节信息,例如变量值和程序状态等。
格式化记录提供了一种控制和定制日志消息输出格式的方法,使其更容易阅读和理解。通过使用 Formatter 类,可以创建自定义的格式化记录并将其添加到 logger 对象中,以实现更灵活和有用的日志记录方案。
☔八、记录日志-配置logger
在 logging 模块中,可以使用 basicConfig() 函数或者通过编程的方式来配置 logger 对象的属性和行为。 通常情况下,在应用程序开始执行时调用 basicConfig() 函数即可完成全局的基本配置。
logging.basicConfig参数字段
参数名称 | 描述 |
---|---|
filename | 指定日志输出目标文件的文件名(可以写文件名也可以写文件的完整的绝对路径,写文件名日志放执行文件目录下,写完整路径按照完整路径生成日志文件),指定该设置项后日志信息就不会被输出到控制台了 |
filemode | 指定日志文件的打开模式,默认为’a’。需要注意的是,该选项要在filename指定时才有效 |
format | 指定日志格式字符串,即指定日志输出时所包含的字段信息以及它们的顺序。logging模块定义的格式字段下面会列出。 |
datefmt | 指定日期/时间格式。需要注意的是,该选项要在format中包含时间字段%(asctime)s时才有效 |
level | 指定日志器的日志级别 |
stream | 指定日志输出目标stream,如sys.stdout、sys.stderr以及网络stream。需要说明的是,stream和filename不能同时提供,否则会引发 ValueError异常 |
style | Python 3.2中新添加的配置项。指定format格式字符串的风格,可取值为’%‘、’{‘和’$‘,默认为’%’ |
handlers | Python 3.3中新添加的配置项。该选项如果被指定,它应该是一个创建了多个Handler的可迭代对象,这些handler将会被添加到root logger。需要说明的是:filename、stream和handlers这三个配置项只能有一个存在,不能同时出现2个或3个,否则会引发ValueError异常。 |
%Y 四位数的年份表示(000-9999) %y 两位数的年份表示(00-99) %m 月份(01-12) %d 月内中的一天(0-31) %H 24小时制小时数(0-23) %I 12小时制小时数(01-12) %M 分钟数(00-59) %S 秒(00-59) %p 上午AM 下午 PM
import logging logging.basicConfig(filename='example.log', level=logging.DEBUG, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p') # 记录一条日志消息 logging.info('This is an info message') # 首先调用了 basicConfig() 函数,并传递了一些参数来设置日志记录器的属性。例如,指定了要将日志消息记录到文件 'example.log' 中,设置了默认日志级别为 DEBUG,指定了日期时间格式,以及设置了一个自定义的日志消息格式。 # 之后可以通过标准的日志记录函数(如 logging.info())来记录日志消息,这些函数都将根据 global basicConfig() 配置的内容记录日志。
需要注意的是,如果在多个模块或文件中使用相同的 logger 对象,则必须确保在所有地方都调用了 basicConfig() 函数,或者手动对所有 logger 对象进行配置。否则,可能会出现不同部分记录的日志信息不一致的问题。 总之,无论是使用 basicConfig() 函数还是编程方式来配置 logger 对象,都需要了解每个参数的含义和作用,并根据具体应用场景去设置它们。这些参数包括日志文件名、日志级别、日期时间格式、日志消息格式等方面。
import logging # 配置全局日志记录器属性 logging.basicConfig(filename='example.log', level=logging.DEBUG, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p') # 创建一个 logger 对象 logger = logging.getLogger('my_logger') logger.setLevel(logging.DEBUG) # 给 logger 添加处理程序 ConsoleHandler,将日志消息输出到控制台 ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) logger.addHandler(ch) # 记录不同级别的日志消息 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') logger.critical('This is a critical message')
👊九、流程梳理
# 1、创建一个logger # 2、设置下logger的日志的等级 # 3、创建合适的Handler(FileHandler要有路径) # 4、设置下每个Handler的日志等级 # 5、创建下日志的格式 # 6、向Handler中添加上面创建的格式 # 7、将上面创建的Handler添加到logger中 # 8、打印输出logger.debug\logger.info\logger.warning\logger.error\logger.critical
import logging # 配置全局日志记录器属性 #logging.basicConfig(filename='example.log', level=logging.DEBUG,format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',datefmt='%m/%d/%Y %I:%M:%S %p') # 创建logger,如果参数为空则返回root logger logger = logging.getLogger("nick") logger.setLevel(logging.DEBUG) # 设置logger日志等级 # 创建handler fh = logging.FileHandler("example.log", encoding="utf-8") ch = logging.StreamHandler() # 设置输出日志格式 formatter = logging.Formatter( fmt="%(asctime)s %(name)s %(filename)s %(message)s", datefmt="%Y/%m/%d %X" ) # 注意 logging.Formatter的大小写 # 为handler指定输出格式,注意大小写 fh.setFormatter(formatter) ch.setFormatter(formatter) # 为logger添加的日志处理器 logger.addHandler(fh) logger.addHandler(ch) # 输出不同级别的log logger.warning("警告") logger.info("提示") logger.error("错误")