Python 中的日志记录(Logging)如何配置和使用?

Python日志记录通过logging模块实现,核心组件包括Logger、Handler、Formatter和Filter。使用basicConfig可快速配置,而复杂场景可通过自定义Logger和Handler将日志输出到控制台、文件或滚动文件。相比print,logging支持级别控制(DEBUG、INFO、WARNING、ERROR、CRITICAL),可灵活配置输出目标与格式,适用于调试、监控和生产环境。通过FileHandler写入文件,RotatingFileHandler按大小滚动,TimedRotatingFileHandler按时间滚动,实现高效日志管理。

python 中的日志记录(logging)如何配置和使用?

Python中的日志记录,核心在于通过

logging

模块建立一套结构化的信息捕获、处理和输出机制。它不仅仅是打印消息那么简单,更是一种系统性的管理,让你能够精细控制哪些信息在何时、何地、以何种形式被记录下来,这对于程序的调试、监控和后期维护至关重要。它提供了一种比

print

语句强大得多的方式来理解你的代码在做什么。

解决方案

要配置和使用Python的日志记录,你需要理解几个核心组件:

Logger

(记录器)、

Handler

处理器)、

Formatter

(格式器)和

Filter

(过滤器)。

最基础的用法,可以直接通过

logging.basicConfig()

来快速配置,这对于简单的脚本或开发环境非常方便:

import logging# 配置基本日志,将INFO级别及以上的消息输出到控制台logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')logging.debug('这是一条调试信息') # 不会显示,因为级别低于INFOlogging.info('程序启动了')logging.warning('检测到潜在问题')logging.error('发生了一个错误')logging.critical('系统崩溃!')

当你需要更复杂的控制时,比如将日志同时输出到文件和控制台,或者自定义不同的日志级别和格式,就需要手动创建和配置

Logger

Handler

Formatter

立即学习“Python免费学习笔记(深入)”;

import logging# 1. 获取一个记录器实例logger = logging.getLogger('my_app')logger.setLevel(logging.DEBUG) # 设置记录器最低处理级别为DEBUG# 2. 创建一个文件处理器,用于将日志写入文件file_handler = logging.FileHandler('app.log', encoding='utf-8')file_handler.setLevel(logging.INFO) # 文件处理器只处理INFO及以上级别的日志# 3. 创建一个控制台处理器,用于将日志输出到控制台console_handler = logging.StreamHandler()console_handler.setLevel(logging.DEBUG) # 控制台处理器处理DEBUG及以上级别的日志# 4. 定义日志的格式formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')# 5. 将格式器添加到处理器file_handler.setFormatter(formatter)console_handler.setFormatter(formatter)# 6. 将处理器添加到记录器logger.addHandler(file_handler)logger.addHandler(console_handler)# 现在可以使用logger来记录日志了logger.debug('这条调试信息会出现在控制台')logger.info('这条信息会出现在文件和控制台')logger.warning('这是一个警告,也会出现在两处')try:    1 / 0except ZeroDivisionError:    logger.exception('除零错误发生!') # exception会自动记录堆栈信息

这段代码展示了如何细致地控制日志流向和内容。

getLogger

可以获取一个具名的记录器,这在大型应用中区分不同模块的日志非常有用。通过为不同的

Handler

设置不同的级别,我们可以实现日志分流,比如调试信息只在控制台显示,而重要的错误信息则同时写入文件。

为什么Python的logging模块比简单的print语句更具优势?

说实话,刚开始写Python脚本时,谁不是满屏的

print()

?快速、直接,看一眼就知道结果。但很快你就会发现,当程序规模稍微大一点,或者需要部署到生产环境时,

print()

的局限性就暴露无遗了。

logging

模块之所以是标准库,自有其道理。

首先,它提供了日志级别

DEBUG

,

INFO

,

WARNING

,

ERROR

,

CRITICAL

,这些级别让你能够区分信息的轻重缓急。你可以设置一个全局的阈值,比如在开发时显示所有

DEBUG

信息,而到了生产环境,只记录

INFO

WARNING

及以上的内容。

print()

可没这功能,它就是一股脑儿地输出。

其次,输出目标多样化

print()

只能往标准输出(通常是控制台)打印。但

logging

可以通过不同的

Handler

将日志发送到文件、网络(TCP/UDP)、邮件、HTTP服务器,甚至操作系统的日志系统。这在分布式系统或需要集中式日志管理的场景下,是

print()

望尘莫及的。想象一下,你的程序崩溃了,日志信息自动发送到你的邮箱,这比你盯着控制台找错误要高效得多。

再者,格式化输出

logging.Formatter

让你能自定义日志消息的格式,包含时间戳、日志级别、模块名、文件名、行号、函数名等等。这使得日志信息更具可读性和可追溯性。

print()

要实现这些,你得手动拼接字符串,既麻烦又容易出错。而且,

logging

还能自动处理多线程环境下的日志同步,避免输出混乱。

最后,也是我认为最关键的一点,

logging

提升了代码的可维护性和专业性。它强制你思考日志的用途和重要性,而不是随意地插入打印语句。当你的程序出现问题时,一份结构良好、信息丰富的日志远比一堆无序的

print

输出更能帮助你快速定位问题。它就像是程序运行的“黑匣子”,记录下关键的飞行数据,以便事后分析。

Python日志级别有哪些,如何选择合适的级别?

Python的

logging

模块定义了五个标准的日志级别,它们代表了事件的不同严重程度。理解这些级别并正确使用它们,是有效日志记录的关键。

DEBUG (10):这是最低的级别,用于详细的调试信息。通常只在开发阶段或需要深入排查问题时启用。比如,某个变量的值在特定代码点是什么,某个函数被调用时传入了什么参数。

logger.debug("处理用户请求,用户ID: %s", user_id)

INFO (20):用于确认程序按预期运行的事件。这些是程序正常运行时的“里程碑”信息,可以用来了解程序的整体流程。

logger.info("数据库连接成功")logger.info("任务调度器启动")

WARNING (30):表示发生了意外或将来可能出现问题的情况,但程序仍然能够正常运行。这通常是一些需要注意但不是致命的问题。

logger.warning("配置文件未找到,使用默认设置")logger.warning("缓存刷新失败,将尝试重试")

ERROR (40):由于某个严重的问题,程序无法执行某些功能。这通常意味着某个操作失败了,但整个应用程序可能还没有完全崩溃。

logger.error("文件写入失败:%s", file_path)logger.error("API调用返回错误状态码:%d", status_code)

CRITICAL (50):这是最高的级别,表示发生了非常严重的错误,导致程序本身或系统组件无法继续运行。通常需要立即采取行动。

logger.critical("数据库服务不可用,应用程序即将退出")logger.critical("内存溢出,系统崩溃!")

如何选择合适的级别?

选择日志级别更像是一种艺术,而非严格的科学。我的经验是,从目的出发。

开发阶段:我会把记录器级别设为

DEBUG

,甚至

DEBUG

以下(如果有自定义级别的话),这样我能看到所有细节。每一个分支、每一个变量的变化,都可能成为我调试的线索。测试环境:通常会设为

INFO

DEBUG

,根据测试的深度和对日志量的容忍度来决定。目标是捕获所有潜在问题,同时避免日志文件过大。生产环境:这是最需要谨慎的地方。通常将记录器级别设为

INFO

WARNING

INFO

用于记录关键业务流程的进展,

WARNING

用于提示潜在风险。

ERROR

CRITICAL

是必须捕获的,它们是系统健康状况的晴雨表。在生产环境,

DEBUG

级别的日志通常会被禁用,因为它会产生巨大的日志量,影响性能,并可能暴露敏感信息。

一个好的实践是,“宁滥勿缺”地记录,但“按需过滤”地输出。也就是说,在代码中,你可以在任何你觉得有用的地方打上

DEBUG

INFO

日志。但在实际运行中,通过配置

Handler

的级别来控制最终输出的日志量。这样,当你需要深入调试时,只需调整配置,就能获得更详细的信息,而不需要修改代码。

如何将日志输出到文件或滚动文件?

将日志输出到文件是日志记录最常见的需求之一,因为它提供了持久化的记录,便于事后分析和故障排查。而“滚动文件”机制则解决了日志文件无限增长的问题,避免占用过多磁盘空间。

1. 输出到单个文件 (

FileHandler

)

最直接的方式是使用

logging.FileHandler

。它会将所有日志写入一个指定的文件。

import logginglogger = logging.getLogger('file_logger')logger.setLevel(logging.DEBUG)# 创建一个文件处理器,指定日志文件路径和编码# 默认是'a'模式(追加),如果文件不存在则创建file_handler = logging.FileHandler('my_application.log', encoding='utf-8')file_handler.setLevel(logging.INFO) # 文件中只记录INFO及以上级别的日志formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')file_handler.setFormatter(formatter)logger.addHandler(file_handler)logger.debug("这条调试信息不会写入文件,因为文件处理器级别是INFO")logger.info("程序正常运行")logger.warning("磁盘空间可能不足")logger.error("致命错误发生")

这里需要注意的是,

FileHandler

默认以追加模式(

'a'

)打开文件。如果你希望每次程序启动都清空旧日志并重新开始,可以将

mode='w'

作为参数传递给

FileHandler

2. 输出到滚动文件 (

RotatingFileHandler

TimedRotatingFileHandler

)

当你的应用程序长时间运行,或者产生大量日志时,一个日志文件会变得非常大,这不仅难以管理,也可能耗尽磁盘空间。

RotatingFileHandler

TimedRotatingFileHandler

就是为解决这个问题而设计的。

RotatingFileHandler

:按文件大小滚动

这个处理器会在日志文件达到指定大小时,将其重命名(通常是加上

.1

,

.2

等后缀),然后创建一个新的空文件继续写入日志。它会保留指定数量的旧日志文件。

import loggingfrom logging.handlers import RotatingFileHandlerimport timelogger = logging.getLogger('rotating_logger')logger.setLevel(logging.DEBUG)# 创建一个滚动文件处理器# filename: 日志文件名# maxBytes: 单个日志文件最大字节数,例如 10 * 1024 * 1024 (10MB)# backupCount: 保留的旧日志文件数量rotating_handler = RotatingFileHandler(    'app_rotated.log', maxBytes=10 * 1024 * 1024, backupCount=5, encoding='utf-8')rotating_handler.setLevel(logging.INFO)formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')rotating_handler.setFormatter(formatter)logger.addHandler(rotating_handler)for i in range(1000): # 模拟写入大量日志    logger.info(f"这是第 {i} 条日志消息,程序正在正常运行。")    time.sleep(0.01) # 稍微暂停,以便观察文件滚动

app_rotated.log

达到10MB时,它会被重命名为

app_rotated.log.1

,然后创建一个新的

app_rotated.log

。当新的

app_rotated.log

再次达到10MB时,

app_rotated.log.1

会被重命名为

app_rotated.log.2

app_rotated.log

变为

app_rotated.log.1

,再创建一个新的

app_rotated.log

。这个过程会持续,直到达到

backupCount

的限制,最旧的文件会被删除。

TimedRotatingFileHandler

:按时间间隔滚动

如果你更希望日志文件按天、按小时或按分钟滚动,

TimedRotatingFileHandler

是更好的选择。

import loggingfrom logging.handlers import TimedRotatingFileHandlerimport timelogger = logging.getLogger('timed_rotating_logger')logger.setLevel(logging.DEBUG)# 创建一个按时间滚动的处理器# filename: 日志文件名# when: 滚动周期,例如 'h' (小时), 'd' (天), 'midnight' (每天午夜)# interval: 滚动间隔,例如 when='h', interval=1表示每小时滚动一次# backupCount: 保留的旧日志文件数量timed_rotating_handler = TimedRotatingFileHandler(    'app_timed.log', when='midnight', interval=1, backupCount=7, encoding='utf-8')timed_rotating_handler.setLevel(logging.INFO)formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')timed_rotating_handler.setFormatter(formatter)logger.addHandler(timed_rotating_handler)# 模拟日志写入for i in range(50):    logger.info(f"这是第 {i} 条定时滚动日志消息。")    time.sleep(0.5)
when

参数可以设置为:

's'

:秒

'm'

:分钟

'h'

:小时

'd'

:天

'w0'

'w6'

:每周的某一天(w0=周一)

'midnight'

:每天午夜

使用滚动文件处理器是生产环境中日志管理的标准做法。它既保证了日志的完整性,又有效地控制了磁盘使用,是应用程序稳定运行不可或缺的一部分。

以上就是Python 中的日志记录(Logging)如何配置和使用?的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1369780.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月14日 09:57:33
下一篇 2025年12月14日 09:57:52

相关推荐

  • CSS mask属性无法获取图片:为什么我的图片不见了?

    CSS mask属性无法获取图片 在使用CSS mask属性时,可能会遇到无法获取指定照片的情况。这个问题通常表现为: 网络面板中没有请求图片:尽管CSS代码中指定了图片地址,但网络面板中却找不到图片的请求记录。 问题原因: 此问题的可能原因是浏览器的兼容性问题。某些较旧版本的浏览器可能不支持CSS…

    2025年12月24日
    900
  • SASS 中的 Mixins

    mixin 是 css 预处理器提供的工具,虽然它们不是可以被理解的函数,但它们的主要用途是重用代码。 不止一次,我们需要创建多个类来执行相同的操作,但更改单个值,例如字体大小的多个类。 .fs-10 { font-size: 10px;}.fs-20 { font-size: 20px;}.fs-…

    2025年12月24日
    000
  • 为什么设置 `overflow: hidden` 会导致 `inline-block` 元素错位?

    overflow 导致 inline-block 元素错位解析 当多个 inline-block 元素并列排列时,可能会出现错位显示的问题。这通常是由于其中一个元素设置了 overflow 属性引起的。 问题现象 在不设置 overflow 属性时,元素按预期显示在同一水平线上: 不设置 overf…

    2025年12月24日 好文分享
    400
  • 网页使用本地字体:为什么 CSS 代码中明明指定了“荆南麦圆体”,页面却仍然显示“微软雅黑”?

    网页中使用本地字体 本文将解答如何将本地安装字体应用到网页中,避免使用 src 属性直接引入字体文件。 问题: 想要在网页上使用已安装的“荆南麦圆体”字体,但 css 代码中将其置于第一位的“font-family”属性,页面仍显示“微软雅黑”字体。 立即学习“前端免费学习笔记(深入)”; 答案: …

    2025年12月24日
    000
  • 如何解决本地图片在使用 mask JS 库时出现的跨域错误?

    如何跨越localhost使用本地图片? 问题: 在本地使用mask js库时,引入本地图片会报跨域错误。 解决方案: 要解决此问题,需要使用本地服务器启动文件,以http或https协议访问图片,而不是使用file://协议。例如: python -m http.server 8000 然后,可以…

    2025年12月24日
    200
  • 为什么我的特定 DIV 在 Edge 浏览器中无法显示?

    特定 DIV 无法显示:用户代理样式表的困扰 当你在 Edge 浏览器中打开项目中的某个 div 时,却发现它无法正常显示,仔细检查样式后,发现是由用户代理样式表中的 display none 引起的。但你疑问的是,为什么会出现这样的样式表,而且只针对特定的 div? 背后的原因 用户代理样式表是由…

    2025年12月24日
    200
  • inline-block元素错位了,是为什么?

    inline-block元素错位背后的原因 inline-block元素是一种特殊类型的块级元素,它可以与其他元素行内排列。但是,在某些情况下,inline-block元素可能会出现错位显示的问题。 错位的原因 当inline-block元素设置了overflow:hidden属性时,它会影响元素的…

    2025年12月24日
    000
  • 为什么 CSS mask 属性未请求指定图片?

    解决 css mask 属性未请求图片的问题 在使用 css mask 属性时,指定了图片地址,但网络面板显示未请求获取该图片,这可能是由于浏览器兼容性问题造成的。 问题 如下代码所示: 立即学习“前端免费学习笔记(深入)”; icon [data-icon=”cloud”] { –icon-cl…

    2025年12月24日
    200
  • 为什么使用 inline-block 元素时会错位?

    inline-block 元素错位成因剖析 在使用 inline-block 元素时,可能会遇到它们错位显示的问题。如代码 demo 所示,当设置了 overflow 属性时,a 标签就会错位下沉,而未设置时却不会。 问题根源: overflow:hidden 属性影响了 inline-block …

    2025年12月24日
    000
  • 为什么我的 CSS 元素放大效果无法正常生效?

    css 设置元素放大效果的疑问解答 原提问者在尝试给元素添加 10em 字体大小和过渡效果后,未能在进入页面时看到放大效果。探究发现,原提问者将 CSS 代码直接写在页面中,导致放大效果无法触发。 解决办法如下: 将 CSS 样式写在一个单独的文件中,并使用 标签引入该样式文件。这个操作与原提问者观…

    2025年12月24日
    000
  • 为什么我的 em 和 transition 设置后元素没有放大?

    元素设置 em 和 transition 后不放大 一个 youtube 视频中展示了设置 em 和 transition 的元素在页面加载后会放大,但同样的代码在提问者电脑上没有达到预期效果。 可能原因: 问题在于 css 代码的位置。在视频中,css 被放置在单独的文件中并通过 link 标签引…

    2025年12月24日
    100
  • 为什么在父元素为inline或inline-block时,子元素设置width: 100%会出现不同的显示效果?

    width:100%在父元素为inline或inline-block下的显示问题 问题提出 当父元素为inline或inline-block时,内部元素设置width:100%会出现不同的显示效果。以代码为例: 测试内容 这是inline-block span 效果1:父元素为inline-bloc…

    2025年12月24日
    400
  • 使用 Mask 导入本地图片时,如何解决跨域问题?

    跨域疑难:如何解决 mask 引入本地图片产生的跨域问题? 在使用 mask 导入本地图片时,你可能会遇到令人沮丧的跨域错误。为什么会出现跨域问题呢?让我们深入了解一下: mask 框架假设你以 http(s) 协议加载你的 html 文件,而当使用 file:// 协议打开本地文件时,就会产生跨域…

    2025年12月24日
    200
  • React 或 Vite 是否会自动加载 CSS?

    React 或 Vite 是否自动加载 CSS? 在 React 中,如果未显式导入 CSS,而页面却出现了 CSS 效果,这可能是以下原因造成的: 你使用的第三方组件库,例如 AntD,包含了自己的 CSS 样式。这些组件库在使用时会自动加载其 CSS 样式,无需显式导入。在你的代码示例中,cla…

    2025年12月24日
    000
  • React 和 Vite 如何处理 CSS 加载?

    React 或 Vite 是否会自动加载 CSS? 在 React 中,默认情况下,使用 CSS 模块化时,不会自动加载 CSS 文件。需要手动导入或使用 CSS-in-JS 等技术才能应用样式。然而,如果使用了第三方组件库,例如 Ant Design,其中包含 CSS 样式,则这些样式可能会自动加…

    2025年12月24日
    000
  • ElementUI el-table 子节点选中后为什么没有打勾?

    elementui el-table子节点选中后没有打勾? 当您在elementui的el-table中选择子节点时,但没有出现打勾效果,可能是以下原因造成的: 在 element-ui 版本 2.15.7 中存在这个问题,升级到最新版本 2.15.13 即可解决。 除此之外,请确保您遵循了以下步骤…

    2025年12月24日
    200
  • 您不需要 CSS 预处理器

    原生 css 在最近几个月/几年里取得了长足的进步。在这篇文章中,我将回顾人们使用 sass、less 和 stylus 等 css 预处理器的主要原因,并向您展示如何使用原生 css 完成这些相同的事情。 分隔文件 分离文件是人们使用预处理器的主要原因之一。尽管您已经能够将另一个文件导入到 css…

    2025年12月24日
    000
  • CSS 中如何正确使用 box-shadow 设置透明度阴影?

    css 中覆盖默认 box-shadow 样式时的报错问题 在尝试修改导航栏阴影时遇到报错,分析发现是 box-shadow 样式引起的问题。 问题原因 使用 !important 仍无法覆盖默认样式的原因在于,你使用了 rgb() 而不是 rgba(),这会导致语法错误。 立即学习“前端免费学习笔…

    2025年12月24日
    300
  • 为何scss中嵌套使用/*rtl:ignore*/无法被postcss-rtl插件识别?

    postcss-rtl插件为何不支持在scss中嵌套使用/*rtl:ignore*/ 在使用postcss-rtl插件时,如果希望对某个样式不进行转换,可以使用/*rtl:ignore*/在选择器前面进行声明。然而,当样式文件为scss格式时,该声明可能会失效,而写在css文件中则有效。 原因 po…

    2025年12月24日
    000
  • Bear 博客上的浅色/深色模式分步指南

    我最近使用偏好颜色方案媒体功能与 light-dark() 颜色函数相结合,在我的 bear 博客上实现了亮/暗模式切换。 我是这样做的。 第 1 步:设置 css css 在过去几年中获得了一些很酷的新功能,包括 light-dark() 颜色函数。此功能可让您为任何元素指定两种颜色 &#8211…

    2025年12月24日
    100

发表回复

登录后才能评论
关注微信