万字长文 - Python 日志记录器logging 百科全书 之 基础配置

在这里插入图片描述

万字长文 - Python 日志记录器logging 百科全书 之 基础配置

前言

在日常的开发中工作中,日志记录扮演着不可或缺的角色。它不仅能让我们了解应用程序的运行状况,还能帮助我们定位并解决各种问题。

  • 最基本的,它记录了应用程序的运行情况,我们可以从日志文件中了解到程序的运行的基本信息;

  • 其次,当应用程序奔溃时,我们可以从日志文件中快速定位到应用程序崩溃前的状态,帮助我们找出问题所在;

  • 或者,应用程序的某些功能表现不佳,日志可以帮助我们找到性能瓶颈,从而进行调优。

总而言之,日志记录可以帮助我们快速定位并解决程序中的错误,实时监控系统运行状态,及时发现并处理问题。

在这篇文章中,我将介绍 Pythonlogging 模块,它是一个Python标准库。

它可以帮助我们完成应用程序生命周期中的所有的日志记录任务。让我们踏上这个旅程吧!

念念碎🎊🎊

本意是分享关于一篇Python中的logging模块的日志记录功能。

文章标题也都命名好了,就叫 《万字长文 - Python 日志记录器logging 百科全书》

但是在文章的编写的过程中我发现,单单是关于基础配置已经超10000字数了。

全文写完的话,估计得5w+字数吧,文章太长就不方便查阅啦!

所以我就做了拆分,这里是第一篇。关于logging的基础配置!

后面还会有:

  • 日志回滚
  • 高级配置
  • 日志过滤
  • 日志处理器
  • 性能优化

等等知识点,感兴趣的读者朋友们可以一起学习哦!


知识点📖📖

模块释义
loggingPython 的日志记录工具,标准库

导入模块

import logging

官方示例

官方示例:日志指南 — Python 3.12.0 文档

我们先来从一个官方的示例入手,逐步来为读者朋友们介绍logging

记录日志到文件

import logging

# 基础配置
logging.basicConfig(filename='example.log', encoding='utf-8', level=logging.DEBUG)

# 记录不同级别的日志
logging.debug('This message should go to the log file')
logging.info('So should this')
logging.warning('And this, too')
logging.error('And non-ASCII stuff, too, like Øresund and Malmö')

在这个例子中,首先导入了logging模块;

并使用logging.basicConfig函数来进行基本配置。这是配置日志系统的最简单方式。在这个示例中,指定了三个关键参数:

  • filename='example.log':这告诉logging模块将日志消息写入到example.log文件中。
  • encoding='utf-8':这确保了即使日志消息包含非ASCII字符(如“Øresund”和“Malmö”)也能被正确记录。
  • level=logging.DEBUG:这设置了日志级别为DEBUG,意味着所有级别(DEBUG, INFO, WARNING, ERROR, CRITICAL)的日志都会被记录。

下面是关官方文档对于logging的一些方法的注解:

  • 对于简单的日志使用来说日志功能提供了一系列便利的函数。它们是 debug()info()warning()error()critical()。(可以理解为是另一种print,也是作用于打印)
你想要执行的任务此任务最好的工具
对于命令行或程序的应用,结果显示在控制台。print()
在对程序的普通操作发生时提交事件报告(比如:状态监控和错误调查)logging.info() 函数(当有诊断目的需要详细输出信息时使用 logging.debug() 函数)
提出一个警告信息基于一个特殊的运行时事件warnings.warn() 位于代码库中,该事件是可以避免的,需要修改客户端应用以消除告警logging.warning() 不需要修改客户端应用,但是该事件还是需要引起关注
对一个特殊的运行时事件报告错误引发异常
报告错误而不引发异常(如在长时间运行中的服务端进程的错误处理)logging.error(), logging.exception()logging.critical() 分别适用于特定的错误及应用领域

不出意外的话,你会在example.log的日志文件中看到以下日志信息:

在这里插入图片描述

基础配置

在进行日志记录时候,需要考虑的是如何配置日志。这包括定义日志文件的名称、格式,以及确定记录哪些级别的日志信息等。

在前面 官方示例 ,初步接触到了logging的基础配置和日志级别,在这里做详细介绍。

basicConfig

值得注意的是,basicConfig() 在程序运行期间只应被调用一次,通常是在程序的开始处定义。但不管调用多少次,只有第一次的调用会生效,后续的调用将被忽略。

先来看 basicConfig(基础配置)

basicConfiglogging模块的一个方法,下面 logging.basicConfig() 函数的主要配置参数及其描述。

参数描述示例值/备注
filename指定一个文件来保存日志。'myapp.log'
filemode指定日志文件的打开模式。'a'(追加模式)、'w'(写模式)
format定义日志消息的格式。'%(asctime)s - %(levelname)s - %(message)s'
datefmt定义时间格式(用于 format 中的 %(asctime)s)。'%Y-%m-%d %H:%M:%S'
style决定 format 字符串的风格。'%'(默认)、'{''$'
level设置日志的基本级别。logging.INFO, logging.DEBUG, 等
stream指定日志消息的输出流。sys.stdout, sys.stderr
handlers指定一个或多个日志处理器,而不是使用 filenamefilemode[logging.FileHandler('filename'), logging.StreamHandler()]
force强制覆盖任何已经存在的日志配置(Python 3.8+)。TrueFalse
encoding指定文件的编码方式(仅当 filename 被使用时)。'utf-8', 'ascii'
errors指定如何处理编码错误(仅当 filename 被使用时)。'strict', 'replace', 'ignore'

一个简单的 basicConfig 使用示例可能是这样的:

  • 在这个示例中,日志级别被设置为 INFO,模式为W 写模式(即覆盖)。日志格式包括时间戳、日志级别和消息内容。日志会被写入到 app.log 文件中。
import logging

# 基础配置
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S',
    filename='example.log',
    filemode='w',
    errors='ignore')

# 记录不同级别的日志
logging.debug('This message should go to the log file')
logging.info('So should this')
logging.warning('And this, too')
logging.error('And non-ASCII stuff, too, like Øresund and Malmö')

修改一下上面的 官方示例 的代码,将basicConfig的配置替换。如果没有意外的话,你会在example.log的日志文件中看到以下日志信息:

在这里插入图片描述

如果你足够细心,你会有以下发现:

  • 这里的日志内容值有3行,相比上面的 官方示例 的日志内容少了1行;
  • 日志内容带有时间,且内容以 - 做分隔;
  • 非ASCII字符不见了。

这里涉及到三个参数,对应上面的三个变化:

  1. 日志级别
  2. 格式设置
  3. 错误处理

下面分别来介绍一下这 三个变化三个参数

日志级别

基于日志的内容和重要性,我们通常需要设定不同的日志级别。

Python的logging模块提供了强大的日志记录功能,包括五个日志级别:DEBUG、INFO、WARNING、ERROR和CRITICAL。通过设置不同的日志级别,我们可以控制日志输出的详细程度。

日志功能应以所追踪事件级别或严重性而定。各级别适用性如下(以严重性递增):

  • 这份表格是 官方文档 拿下来的,我添加了一列使用场景

logging默认的级别是 WARNING,意味着只会追踪该级别及以上的事件,除非更改日志配置。

级别数值含义 / 何时使用使用场景
logging.NOTSET0当在日志记录器上设置时,表示将查询上级日志记录器以确定生效的级别。 如果仍被解析为 NOTSET,则会记录所有事件。 在处理句柄上设置时,所有事件都将被处理。一般不直接使用,用于继承父级日志记录器的级别或允许记录所有事件。
logging.DEBUG10详细的信息,通常只有试图诊断问题的开发人员才会感兴趣。用于开发阶段,用于详细追踪事件、变量值,帮助诊断问题。
logging.INFO20确认程序按预期运行。用于生产环境,记录常规操作,如程序启动、运行状态或处理流程。
logging.WARNING30表明发生了意外情况,或近期有可能发生问题(例如‘磁盘空间不足’)。 软件仍会按预期工作。用于警告可能会影响程序性能但不影响程序继续运行的问题。
logging.ERROR40由于严重的问题,程序的某些功能已经不能正常执行用于记录程序运行中出现的错误,这些错误会影响某些功能的执行。
logging.CRITICAL50严重的错误,表明程序已不能继续执行用于记录严重错误,如程序崩溃、关键服务失效,需要立即关注的问题。

这些日志级别之间的关系是层级的,也就是说,在设置为某个级别时,会记录该级别以及更高级别的日志。例如,如果日志级别设置为 WARNING,则会记录 WARNINGERRORCRITICAL 级别的消息,但不会记录 DEBUGINFO 级别的消息。

可以理解为,每个级别都包含了比它更高级别的日志信息,而忽略了比它更低级别的信息。所以,选择合适的日志级别可以帮助你筛选出最关心的信息,而忽略不那么重要的细节。


以下是在日常开发或者生产环境中,对应场景建议使用的日志级别。

环境推荐日志级别理由
生产环境INFOWARNING关注程序正常运行和潜在问题,INFO 记录正常操作,WARNING 提示可能的问题但不影响运行。
测试环境DEBUGINFODEBUG 提供详细信息以诊断问题,INFO 提供较少但重要的信息。适用于测试和问题排查。
日常开发DEBUGINFODEBUG 适用于详细追踪和开发阶段,INFO 用于较稳定或需关注主要操作的情况。

以上提供了一个基本的指导,帮助读者朋友们根据不同的应用场景选择合适的日志级别。

然而,具体使用哪个级别还需要根据你的具体需求和项目的复杂度来决定。在实际应用中,需要根据实际情况做出调整。甚至可以在不同阶段动态调整日志级别以满足特定需求。

选择适当的级别有助于确保日志既提供了足够的信息以监控应用程序,又可以避免过多的冗余信息。


解释:日志内容为什么少了一行?

  • 因为 basicConfig 代码中日志级别设置为INFO,所以只记录INFOWARNINGERRORCRITICAL 级别的日志信息,
  • basicConfig 较比 官方示例 的日志级别少了DEBUG,于是内容就少了一行。

格式设置

如果想使用不同的风格,则需要相应地修改 format 字符串,并设置 style 参数。

style

在 Python 的 logging 模块中,style 参数用于指定 format 字符串的风格。这允许选择不同的字符串格式化方法。有三种风格可供选择:

  1. '%' 风格:这是默认的格式化风格,使用传统的 printf 风格的格式化字符串。例如:'%(asctime)s - %(levelname)s - %(message)s'

  2. '{' 风格:使用 str.format() 方法的格式化字符串。例如:'{asctime} - {levelname} - {message}'

  3. '$' 风格:使用 string.Template 风格的格式化字符串。例如:'${asctime} - ${levelname} - ${message}'

根据自己选择的 style,我们需要相应地调整 format 参数中的字符串,否则会抛出 ValueError 异常。

选择哪种风格主要取决于个人偏好以及项目中已有的编码风格。'%' 风格是最传统的,而 '{''$' 提供了更现代和灵活的字符串格式化选项(但他们记录的内容是一致的)。

示例的配置如下所示:

  • 使用 '%' 风格:

    logging.basicConfig(level=logging.INFO,
                        format='%(asctime)s - %(levelname)s - %(message)s',
                        style='%')
    
  • 使用 '{' 风格:

    logging.basicConfig(level=logging.INFO,
                        format='{asctime} - {levelname} - {message}',
                        style='{')
    
  • 使用 '$' 风格:

    logging.basicConfig(level=logging.INFO,
                        format='${asctime} - ${levelname} - ${message}',
                        style='$')
    

在 Python logging 模块中,format 字符串可以包含多种格式化字段,这些字段用于定义日志消息的具体内容。以下是一些常用的格式化字段,以表格形式展示:

格式化字段描述
%(name)sLogger 的名字(即创建 Logger 实例时指定的名称)
%(levelno)s日志级别的数值表示(如 10, 20, 30, …)
%(levelname)s日志级别的文本表示(如 ‘DEBUG’, ‘INFO’, ‘WARNING’, 等)
%(pathname)s调用日志记录函数的源码文件的全路径
%(filename)spathname 的文件名部分
%(module)sfilename 的模块名部分
%(funcName)s调用日志记录函数的函数名
%(lineno)d调用日志记录函数的源代码行号
%(asctime)s创建日志记录的时间。默认格式为 ‘2023-11-07 09:13:45,896’
%(thread)d线程ID
%(threadName)s线程名
%(process)d进程ID
%(message)s日志消息本身

我们可以根据需要在 format 字符串中组合使用这些字段。例如:

  • 这个配置会产生包含时间戳、Logger 名称、日志级别和消息本身的日志记录。
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')

常用配置:

在 Python logging 中,最常用的 format 字段取决于项目的日志需求和个人偏好,以下是一些被频繁使用的字段:

  1. %(asctime)s:显示日志事件发生的时间。这是非常有用的信息,因为它帮助我们知道什么时候发生了什么事件;
  2. %(levelname)s:显示日志消息的级别(如 DEBUG, INFO, WARNING, ERROR, CRITICAL)。这是不可或缺的;
  3. %(message)s:显示日志消息本身。这是日志记录的核心部分,包含了事件或数据的实际描述。
  4. %(name)s:显示 Logger 的名字。如果在一个大型应用中使用多个 logger,这可以帮助我们确定哪个 logger 产生了消息。
  5. %(filename)s%(lineno)d:这些字段显示产生日志消息的源文件名和行号。在调试时,它们能帮助我们快速定位问题所在的代码位置。

一个典型的 format 配置可能是这样的:

logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(filename)s:%(lineno)d - %(message)s')

这个配置提供了日志消息的时间、来源、级别、位置(文件和行号)和具体内容,适用于大多数常规日志记录需求。但具体的配置还是需要根据项目需求和你的具体情况,选择添加或省略某些字段。


解释:日志内容带有时间

  • 因为代码中使用了 format='%(asctime)s - %(levelname)s - %(message)s'

错误处理

指定如何处理编码错误(仅当 filename 被使用时生效)

在 Python 的 logging 模块中,errors 参数是用于配置日志文件写入时的错误处理策略。这个参数仅在使用 filename 参数(即将日志写入到文件)时有效,并且通常与 encoding 参数一起使用。errors 参数定义了在写入日志文件时如何处理那些无法根据指定的编码(如 UTF-8)编码的字符。

以下是几种常见的 errors 参数配置选项及其含义:

  1. 'strict':这是默认的错误处理方式。如果遇到无法按照指定编码的字符,会引发 UnicodeEncodeError 异常,导致日志记录中断;

  2. 'ignore':忽略无法编码的字符。这意味着那些无法编码的字符将被静默地从日志消息中删除,而不会抛出异常;

  3. 'replace':用一个替代字符(通常是 '?')来替换无法编码的字符。这种方式可以避免编码错误的异常,同时保留了无法编码字符的占位符,从而使你知道在原始消息中存在某些问题;

  4. 'backslashreplace':用 Python 的反斜杠转义序列来替换无法编码的字符。这种方式在保持日志可读性的同时,提供了关于原始字符的更多信息;

  5. 'xmlcharrefreplace':用适合于 XML 和 HTML 的字符引用来替换无法编码的字符。

例如,如果我们希望在写入日志文件时避免因为编码错误而中断日志记录,可以选择使用 'replace''ignore'

logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s - %(levelname)s - %(message)s',
                    filename='example.log',
                    filemode='w',
                    encoding='utf-8',
                    errors='replace')

在这个例子中,任何无法按照 UTF-8 编码的字符都会被 '?' 替换,从而保证日志记录的连续性。这种配置对于多语言环境或处理包含特殊字符的数据时尤其有用。


解释:非ASCII字符不见了

  • errors设置为**ignore**,则会忽略非ASCII字符

示例代码🎈🎈

一般

这个示例包括了日志的基本设置,如日志级别、格式、文件名等,以及如何在代码中使用不同级别的日志记录。

在具体的使用时候,我们只需要在应用程序中将对应的logging.debug、logging.info…等方法记录日志即可。

import logging

# 基础配置
logging.basicConfig(
    level=logging.INFO,  # 设置日志级别为INFO
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',  # 设置日志格式
    datefmt='%Y-%m-%d %H:%M:%S',  # 设置时间格式
    filename='app.log',  # 日志输出到app.log文件
    filemode='w',  # 写入模式
    encoding='utf-8',  # 文件编码
    errors='ignore'  # 忽略编码错误
)

# 记录不同级别的日志
logging.debug('Debug message')  # 通常用于详细的系统诊断信息
logging.info('Info message')  # 通常用于记录程序运行状态或操作
logging.warning('Warning message')  # 用于警告信息,可能的问题
logging.error('Error message')  # 用于记录错误事件
logging.critical('Critical message')  # 用于记录严重的错误事件,可能导致程序终止

高级

进一步的,应用程序在运行时候,特别是在复杂的应用程序中,可能无法预见所有可能的错误场景。这个时候,最好的做法是让程序能够优雅地终止或继续运行。

在下面的示例中:

  • setup_logging 函数配置了基础的日志记录设置。
  • handle_exception 作为全局异常处理器,用于捕获未被局部 try-except 块捕获的异常,并使用 logging 记录异常信息。
  • my_function 演示了日志记录的常规用法,包括记录操作开始的信息和捕获处理异常的情况。
  • 通过 sys.excepthook 设置了自定义的全局异常处理函数。

handle_exception 作为全局异常处理器,负责捕获并处理整个程序中未被其他 try-except 块捕获的异常。函数解释如下:

  • 对于所有其他类型的异常,函数使用 logging.error 来记录异常信息。exc_info 参数被设置为一个包含异常类型、值和回溯信息的元组,这样 logging 模块可以记录完整的异常堆栈信息。

这样,即使在 my_function 中抛出的除以零异常没有被显式捕获,全局异常处理器也会捕获它,并将相关信息记录到日志文件中。

import logging
import sys


def setup_logging():
    logging.basicConfig(
        level=logging.INFO,
        format='%(asctime)s - %(levelname)s - %(message)s',
        datefmt='%Y-%m-%d %H:%M:%S',
        filename='app.log',
        filemode='w',
        encoding='utf-8',
        errors='ignore'
    )


def handle_exception(exc_type, exc_value, exc_traceback):
    """
    全局异常处理函数,用于捕获并处理所有未被捕获的异常。

    Args:
        exc_type: 异常的类型,例如 ZeroDivisionError
        exc_value: 异常实例,包含异常消息等信息。
        exc_traceback: 一个 traceback 对象,包含异常发生时的调用堆栈信息。

    Returns:

    """
    # 使用 logging 记录异常信息
    logging.error("Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback))


def my_function():
    # 潜在的异常操作
    result = 10 / 0
    return result


if __name__ == '__main__':
    setup_logging()
    sys.excepthook = handle_exception
    # 运行示例函数
    my_function()

使用场景和注意事项

handle_exception 作为全局异常处理器,用于捕获那些在程序的其他部分未被明确捕获的异常。在使用这个全局异常处理器时,应注意:

  • 它不应替代在函数或方法内部对特定异常的具体处理。对于已知可能发生的异常,应在相应的代码区域内使用 try-except 块进行处理。
  • 这个处理器更适合用于捕获意外异常,记录异常信息,并在可能的情况下让程序能够优雅地终止或继续运行。

总结🎞🎞

在这篇文章中,我们介绍了 Python 的 logging 模块,这是一个非常强大且灵活的日志记录工具,是 Python 标准库的一部分。通过合理配置和使用 logging 模块,我们可以有效地记录程序的运行情况,监控系统状态,并在必要时定位和解决问题。

我们讨论了 logging 的基础配置,如 basicConfig 方法,以及如何设置日志级别、格式和输出目的地等。我们还探讨了不同日志级别的适用场景,以及如何根据开发环境、测试环境或生产环境选择合适的日志级别。

此外,我们解释了格式化日志消息的不同风格,如 % 风格、{} 风格和 $ 风格,并展示了如何根据个人喜好和项目需求选择合适的风格。我们还讨论了 errors 参数在处理非 ASCII 字符时的重要性,以及如何配置它以避免编码问题。

总之,合理使用 logging 模块能够极大地提升程序的可维护性和可靠性。通过定制化的日志记录策略,我们可以确保在需要时总能获取到足够的信息,以便快速响应和解决任何问题。

后话

本次分享到此结束,

see you~~🐱‍🏍🐱‍🏍

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/120840.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【论文阅读】Progressive Spatio-Temporal Prototype Matching for Text-Video Retrieval

资料链接 论文链接:https://openaccess.thecvf.com/content/ICCV2023/papers/Li_Progressive_Spatio-Temporal_Prototype_Matching_for_Text-Video_Retrieval_ICCV_2023_paper.pdf 代码链接:https://github.com/imccretrieval/prost 背景与动机 文章发…

百分点科技受邀参加“第五届治理现代化论坛”

11月4日,由北京大学政府管理学院主办的“面向新时代的人才培养——第五届治理现代化论坛”举行,北京大学校党委常委、副校长、教务长王博,政府管理学院院长燕继荣参加开幕式并致辞,百分点科技董事长兼CEO苏萌受邀出席论坛&#xf…

Spring Cloud学习(二)【Eureka注册中心】

文章目录 Eureka 注册中心Eureka 的作用 动手实践搭建 EurekaServer服务注册服务发现 Ribbon 负载均衡负载均衡原理IRule 接口(负载均衡策略)饥饿加载 Eureka 注册中心 服务调用出现的问题 不能采用硬编码服务消费者该如何获取服务提供者的地址信息&am…

06【保姆级】-GO语言的运算符

之前我学过C、Java、Python语言时总结的经验: 先建立整体框架,然后再去抠细节。先Know how,然后know why。先做出来,然后再去一点点研究,才会事半功倍。适当的囫囵吞枣。因为死抠某个知识点很浪费时间的。对于GO语言&a…

JDBC(二)

第4章 操作BLOB类型字段 4.1 MySQL BLOB类型 MySQL中,BLOB是一个二进制大型对象,是一个可以存储大量数据的容器,它能容纳不同大小的数据。 插入BLOB类型的数据必须使用PreparedStatement,因为BLOB类型的数据无法使用字符串拼接写…

OAuth 2.0实现统一认证

OAuth 2.0协议概念: OAuth 是 Open Authorization 的简写。OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 OAuth 的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第…

Kotlin HashMap entries.filter过滤forEach

Kotlin HashMap entries.filter过滤forEach fun main(args: Array<String>) {val hashMap HashMap<String, Int>()hashMap["a"] 1hashMap["b"] 2hashMap["c"] 3println(hashMap)hashMap.entries.filter {println("filter $…

【MongoDB】索引 – 文本索引(指定语言)

一、语言列表 语言名称 代码 danish da dutch nl english en finnish fi french fr german de hungarian hu italian it norwegian nb portuguese pt romanian ro russian ru spanish es swedish sv turkish tr 二、指定默认语言 创建文本索…

UseGalaxy.cn生信云平台文本文件操作手册

文本文件是生物信息学中应用非常广泛的文本格式&#xff0c;甚至可以说是最重要的文件格式&#xff0c;比如常见的测序下机数据Fastq、参考基因组保存格式Fasta、比对文件SAM&#xff0c;以及突变列表VCF&#xff0c;它们都是文本文件。熟练地进行文本文件的处理&#xff0c;对…

upload-labs-1

文章目录 Pass-01 Pass-01 先上传一个正常的图片&#xff0c;查看返回结果&#xff0c;结果中带有文件上传路径&#xff0c;可以进行利用&#xff1a; 上传一个恶意的webshell&#xff0c;里面写入一句话木马&#xff1a; <?php eval($_POST[cmd]); echo "hello&quo…

【单片机】初次实验:Keil51的使用

哔哩哔哩/CSDN/博客园&#xff1a;萌狼蓝天 延时器 delay(int count){int i,j;for(i0;i<count;i){for(j0;j<1000;j);} } 瞧一瞧 题目要求&#xff1a;P0口接八个发光二极管&#xff0c;先让后面四个灯亮&#xff0c;再让前面四个灯亮&#xff0c;循坏 # include <REGX…

京东数据分析(京东销量):2023年9月京东投影机行业品牌销售排行榜

鲸参谋监测的京东平台9月份投影机市场销售数据已出炉&#xff01; 根据鲸参谋电商数据分析平台的相关数据数据显示&#xff0c;9月份&#xff0c;京东平台投影机的销量为13万&#xff0c;环比下滑约17%&#xff0c;同比下滑约25%&#xff1b;销售额将近2.6亿&#xff0c;环比下…

eNsp下如何使用wireshark抓包

文章目录 拓扑图抓包操作 拓扑图 抓包操作 可以通过下图上的指示 来设置 Time列的显示样式。 这里有个缺点就是就是抓取ensp上的虚拟设备上的数据包时的&#xff0c;年月日时间显示的不对。暂时无解决办法。 一般选择 日期和时间&#xff08;日期和时间与当前标准时间对应上时…

程序员找副业有哪几个方向(纯干货)

前序 关于副业对于我自己的看法一般会先从自身的职业去拓展&#xff0c;毕竟自己所在的行业自己会更清楚有哪些资源去获取&#xff0c;那么首先我们可以先问万能的gpt我们程序员做副业有哪些实用的推荐&#xff0c;看看它怎么说的 外包网站接单&#xff1f; 每次大家提到程序…

python循环队列

导语&#xff1a; 队列是一种先进先出&#xff08;first in first out,FIFO&#xff09;的线性表&#xff0c;是一种常用的数据结构。 它只允许在表的前端&#xff08;front&#xff09;进行删除操作&#xff0c;而在表的后端&#xff08;rear&#xff09;进行插入操作&#…

C语言——计算1!+2!+3!+......+10!

#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h> int main() {int n;int ret 1;int sum 0;for(n 1; n < 10; n){ret * n;sum sum ret;}printf("sum %d\n",sum);return 0; }

C++基础——类与对象

1 概述 C是面向对象的语言&#xff0c;面向对象语言三大特性&#xff1a;封装、继承、多态。 C将万事万物抽象为对象&#xff0c;对象上有其属性和行为。 2 封装 2.1 封装的意义 封装是面向对象的三大特性之一&#xff0c;封装将属性和行为作为一个整体&#xff0c;对属性和…

接口自动化面试题

1.http请求都包含哪些内容&#xff0c;请求头和请求体有哪些内容 请求行/请求头/请求体/空行 请求行&#xff1a;请求方法字段、URL字段、http协议版本 例如&#xff1a;GET /index.html HTTP/1.1 请求方法&#xff1a;GET、POST、PUT、DELETE、OPTIONS、TRACE、CO…

2007-2022年全国各地级市金融机构网点数据

2007-2022年地级市金融机构网点数据 1、时间&#xff1a;2007-2022年 2、指标&#xff1a;行政区划代码、年份、城市名称、所属省份、银行网点数量、其中-政策性银行及国家开发银行营业网点占比、其中-商业银行营业网点数量占比、其中-农村金融机构营业网点数量占比 3、范围…

20.8 OpenSSL 套接字SSL传输文件

有了上面的基础那么传输文件的实现就变得简单了&#xff0c;在传输时通常我们需要打开文件&#xff0c;并每次读入1024个字节的数据包&#xff0c;通过SSL加密传输即可&#xff0c;此处的文件传输功能在原生套接字章节中也进行过详细讲解&#xff0c;此处我们还是使用原来的密钥…