C#转Python第4.7篇:logging:Python 的标准日志库

在 C# 里记日志,用 Console.WriteLine() 或第三方库------Serilog、NLog、log4net,配置复杂但功能强大。

在 Python 里记日志,用 logging 模块------内置的,开箱即用,配置灵活。

C# 的日志生态很丰富,但选择太多反而让人纠结。Python 的 logging 模块虽然简单,但该有的功能都有。

Python 的 logging 模块虽然简单,但该有的功能一个不少------开箱即用才是王道。

基础用法

C# 版本:

复制代码
// 最简单的日志
Console.WriteLine("这是一条日志");

// 使用内置的 Trace/Debug
Trace.WriteLine("跟踪信息");
Debug.WriteLine("调试信息");

// 使用第三方库(如 Serilog)
using var log = new LoggerConfiguration()
    .WriteTo.Console()
    .CreateLogger();

log.Information("这是一条信息日志");
log.Warning("这是一条警告日志");
log.Error("这是一条错误日志");

Python 版本:

复制代码
import logging

# 配置日志
logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)

# 基础日志
logging.debug("这是调试信息")
logging.info("这是信息日志")
logging.warning("这是警告日志")
logging.error("这是错误日志")
logging.critical("这是严重错误")

对比一下:

级别 C# Python
调试 Debug.WriteLine() logging.debug()
信息 log.Information() logging.info()
警告 log.Warning() logging.warning()
错误 log.Error() logging.error()
严重 log.Fatal() logging.critical()

Python 的 logging 模块比 C# 的 Console.WriteLine() 更专业------有级别、有格式、有处理器。

Logger 对象

C# 版本(Serilog):

复制代码
// 创建 Logger
var logger = new LoggerConfiguration()
    .WriteTo.Console()
    .WriteTo.File("logs/app.log", rollingInterval: RollingInterval.Day)
    .CreateLogger();

// 使用 Logger
logger.Information("用户 {UserId} 登录", userId);
logger.Error(ex, "处理请求时出错");

Python 版本:

复制代码
import logging

# 创建 Logger
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

# 添加处理器
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)

file_handler = logging.FileHandler('app.log', encoding='utf-8')
file_handler.setLevel(logging.DEBUG)

# 设置格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
console_handler.setFormatter(formatter)
file_handler.setFormatter(formatter)

# 添加处理器到 Logger
logger.addHandler(console_handler)
logger.addHandler(file_handler)

# 使用 Logger
logger.info("用户 %s 登录", user_id)
logger.error("处理请求时出错", exc_info=True)
特性 C#(Serilog) Python
创建方式 new LoggerConfiguration() logging.getLogger()
输出到控制台 .WriteTo.Console() StreamHandler()
输出到文件 .WriteTo.File() FileHandler()
输出到数据库 .WriteTo.MSSqlServer() 自定义 Handler
格式化 "{UserId}" %(name)s

Python 的 Handler 比 C# 的 Sink 更灵活------可以自定义处理器。

日志格式

C# 版本(Serilog):

复制代码
var logger = new LoggerConfiguration()
    .WriteTo.Console(outputTemplate: 
        "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}")
    .CreateLogger();

Python 版本:

复制代码
import logging

# 自定义格式
formatter = logging.Formatter(
    fmt='[%(asctime)s] %(levelname)-8s %(message)s',
    datefmt='%H:%M:%S'
)

# 使用格式
handler = logging.StreamHandler()
handler.setFormatter(formatter)

常用格式化参数:

参数 说明 C# 对应
%(asctime)s 时间戳 {Timestamp}
%(levelname)s 日志级别 {Level}
%(name)s Logger 名称 {SourceContext}
%(message)s 日志消息 {Message}
%(filename)s 文件名 {FileName}
%(lineno)d 行号 {LineNumber}
%(funcName)s 函数名 {MethodName}

实际场景:Web 应用日志

C# 版本(ASP.NET Core):

复制代码
// appsettings.json
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  }
}

// Program.cs
builder.Host.ConfigureLogging(logging =>
{
    logging.ClearProviders();
    logging.AddConsole();
    logging.AddFile("logs/app-{Date}.txt");
});

Python 版本(Flask):

复制代码
import logging
from logging.handlers import RotatingFileHandler
from flask import Flask

app = Flask(__name__)

# 配置日志
if not app.debug:
    # 文件日志(滚动)
    file_handler = RotatingFileHandler(
        'logs/app.log',
        maxBytes=10240000,  # 10MB
        backupCount=10
    )
    file_handler.setFormatter(logging.Formatter(
        '%(asctime)s %(levelname)s: %(message)s '
        '[in %(pathname)s:%(lineno)d]'
    ))
    file_handler.setLevel(logging.INFO)
    app.logger.addHandler(file_handler)
    
    # 控制台日志
    console_handler = logging.StreamHandler()
    console_handler.setLevel(logging.DEBUG)
    app.logger.addHandler(console_handler)
    
    app.logger.setLevel(logging.INFO)
    app.logger.info('应用启动')

日志处理器(Handler)

C# 的 Sink 和 Python 的 Handler:

处理器 C#(Serilog) Python
控制台 .WriteTo.Console() StreamHandler()
文件 .WriteTo.File() FileHandler()
滚动文件 .WriteTo.File(rollingInterval:) RotatingFileHandler()
HTTP .WriteTo.HTTP() HTTPHandler()
SMTP(邮件) .WriteTo.Email() SMTPHandler()
Syslog .WriteTo.Syslog() SysLogHandler()

Python 的 RotatingFileHandler 比 C# 的滚动文件更灵活------可以设置文件大小和备份数量。

性能考虑

C# 版本:

复制代码
// Serilog 是异步的,性能较好
var logger = new LoggerConfiguration()
    .WriteTo.Async(a => a.Console())
    .CreateLogger();

// 或者用 Microsoft.Extensions.Logging
services.AddLogging(builder =>
{
    builder.AddConsole();
    builder.SetMinimumLevel(LogLevel.Information);
});

Python 版本:

复制代码
import logging
from logging.handlers import QueueHandler, QueueListener
from queue import Queue

# 异步日志(Python 3.12+)
queue = Queue()
queue_handler = QueueHandler(queue)

# 配置处理器
handler = logging.StreamHandler()
listener = QueueListener(queue, handler)
listener.start()

# 使用
logger = logging.getLogger(__name__)
logger.addHandler(queue_handler)
logger.info("异步日志")

Python 3.12+ 支持异步日志,但 C# 的 Serilog 在异步方面更成熟。

设计哲学

C# 的日志是"多选一"------Serilog、NLog、log4net、Microsoft.Extensions.Logging,选择丰富但配置复杂。

Python 的日志是"内置款"------logging 模块开箱即用,简单够用,扩展灵活。

C# 的日志像是"超市购物",品牌众多,任你挑选; Python 的日志像是"便利店",商品不多,但该有的都有。

更深层的原因:

  • C# 的日志生态是社区驱动的,每个库都有自己的设计理念

  • Python 的日志是标准库的,遵循"一种方式做一件事"的哲学

迁移指南:C# 开发者最容易犯的错

  1. 忘记配置级别:默认只显示 WARNING 及以上

  2. 忘记添加 Handler:没有 Handler,日志不会输出

  3. **用 print() 代替 logging**:print() 没有级别、没有格式

  4. 忘记编码 :文件日志需要指定 encoding='utf-8'

  5. **过度使用 logging.debug()**:生产环境应该用 INFO 或更高

坑点提醒

默认级别是 WARNING------需要手动设置:

复制代码
import logging

# 默认只显示 WARNING 及以上
logging.info("这不会显示")  # 不输出
logging.warning("这会显示")  # 输出

# 设置级别
logging.basicConfig(level=logging.DEBUG)
logging.info("现在会显示了")  # 输出

Handler 需要单独添加------Logger 本身不输出:

复制代码
import logging

logger = logging.getLogger(__name__)
# 没有 Handler,不会输出任何内容!

# 添加 Handler
handler = logging.StreamHandler()
logger.addHandler(handler)
logger.info("现在会输出了")

多个 Logger 可能重复输出------注意 Logger 层级:

复制代码
import logging

# 父 Logger
parent = logging.getLogger('app')
parent.addHandler(logging.StreamHandler())

# 子 Logger
child = logging.getLogger('app.module')

# 子 Logger 会继承父 Logger 的 Handler
child.info("这会输出两次!")

一句话总结

Python 的 logging 模块是"内置款"------简单够用,开箱即用,比 C# 的 Console.WriteLine() 专业得多。


📦 示例代码:C# 转 Python 全系列配套练习代码(含 48 章示例)

💬 欢迎点赞、收藏、转发,你的支持是我持续创作的动力!

相关推荐
程序员老陆1 小时前
从汇编层面理解 C++ 多线程
开发语言·c++·程序设计
谢亮_vipxieliang1 小时前
深入理解 JavaScript 数据类型与类型转换
开发语言·javascript·ecmascript
IOT-Power1 小时前
模板方法 + 策略模式
开发语言·c++
EatFan2 小时前
2026 Rust 后端技术栈选型:Axum 0.8 + Tokio + SQLx 全链路怎么搭
开发语言·后端·rust·tokio·serde·axum·sqlx
外收内放2 小时前
Python基础语法练习题(59-原始版本与优化版本)
开发语言·python
ASS-ASH2 小时前
从力学与机械原理角度深度剖析:尊界V800刹车踏板支架断裂事件的技术逻辑
人工智能·python·数据可视化·机械工程·汽车安全·物理仿真·制动系统
xhy_07072 小时前
AI 读了 .env,密钥会原样发给大模型吗?WES Code 的密钥打码(附实测)
人工智能·python·数据挖掘·flask·ai编程·wes code
2401_888859712 小时前
STM32H733 MPU、AXI、FMC学习
java·开发语言·stm32·spring
宝桥南山2 小时前
.NET 11 - 尝试创建一下AGUIServer和AGUIClient(基于新版.NET SDK for AG-UI)
microsoft·ai·微软·c#·aigc·.net