Propagation V.S. Levels checking

部署运行你感兴趣的模型镜像
import logging

root_logger = logging.getLogger()
root_handler = logging.StreamHandler()
root_handler.setFormatter(logging.Formatter('ROOT: %(message)s'))
root_logger.addHandler(root_handler)

# 父Logger配置
parent_logger = logging.getLogger('parent')
parent_handler = logging.StreamHandler()
parent_handler.setFormatter(logging.Formatter('PARENT: %(message)s'))
parent_logger.addHandler(parent_handler)
parent_logger.setLevel(logging.ERROR)

# 子Logger(默认propagate=True)
child_logger = logging.getLogger('parent.child')
child_handler = logging.StreamHandler()
child_handler.setFormatter(logging.Formatter('CHILD: %(message)s'))
child_logger.addHandler(child_handler)
child_logger.setLevel(logging.INFO)
child_logger.info("INFO msg")

Running Result:

/Users/egonever/DjangoByExamples/mysite/logging_demystified/example3.py 
CHILD: INFO msg
PARENT: INFO msg
ROOT: INFO msg

Process finished with exit code 0

Why "INFO msg" was logged three times?

The message "INFO msg" is logged three times due to Python's logging hierarchy and the default propagation behavior (propagate=True). Here's the detailed explanation:

  1. Child Logger Handling
    The child_logger first processes the message through its own handler (child_handler), which outputs:
    CHILD: INFO msg
    This occurs because the message level (INFO) meets the child logger's level (INFO)‌.

  2. Propagation to Parent Logger
    Since propagate=True (default), the message is passed to the parent logger (parent_logger). Despite the parent's level being ERROR, the message is still processed by the parent's handler (parent_handler), resulting in:
    PARENT: INFO msg
    Note: The parent logger's level only filters messages before they reach its handlers, but propagation bypasses this check‌.

  3. Propagation to Root Logger
    The message further propagates to the root logger, which has no level set (defaults to WARNING). However, the root logger's handler (root_handler) still processes the message, producing:
    ROOT: INFO msg
    Similar to the parent logger, the root's level doesn't block propagated messages‌.

Key Points

  • Propagation allows messages to bubble up the logger hierarchy (child → parent → root)‌.
  • Handler levels are independent of logger levels.
  • When a handler is created, the level is set to NOTSET with numeric value 0(which causes all messages to be processed).
  • To avoid duplicate logs, either:
    • Set child_logger.propagate = False, or
    • Configure logger levels and handlers more carefully‌.
      • Explicitly configure handlers' level by using setLevel method.

您可能感兴趣的与本文相关的镜像

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

`propagation = Propagation.NOT_SUPPORTED` 表示以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。以下是其在实际应用中的常见使用场景: #### 日志记录 在系统中,日志记录通常不需要与业务事务绑定在一起。即使业务操作失败,日志记录也应该正常进行,并且不应该影响业务事务的回滚。例如: ```java import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Propagation; @Service public class LogService { @Transactional(propagation = Propagation.NOT_SUPPORTED) public void recordLog(String logMessage) { // 记录日志的具体逻辑 System.out.println("Logging: " + logMessage); } } ``` 在这个例子中,`recordLog` 方法以非事务方式执行,即使调用该方法的业务方法处于事务中,也不会影响日志记录操作,并且不会因为日志记录操作的异常导致业务事务回滚。 #### 缓存更新 缓存更新操作通常不需要参与业务事务。例如,在更新数据库数据后,需要更新缓存中的数据,缓存更新操作可以使用 `Propagation.NOT_SUPPORTED` 以非事务方式执行: ```java import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Propagation; @Service public class CacheService { @Transactional(propagation = Propagation.NOT_SUPPORTED) public void updateCache(String key, Object value) { // 更新缓存的具体逻辑 System.out.println("Updating cache: key=" + key + ", value=" + value); } } ``` 在这个例子中,`updateCache` 方法以非事务方式执行,即使调用该方法的业务方法处于事务中,缓存更新操作也不会影响业务事务的执行。 #### 性能优化的查询操作 对于一些查询操作,如果不需要事务的支持,使用 `Propagation.NOT_SUPPORTED` 可以避免事务带来的开销,提高性能。例如: ```java import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Propagation; @Service public class QueryService { @Transactional(propagation = Propagation.NOT_SUPPORTED) public Object queryData() { // 查询数据的具体逻辑 return new Object(); } } ``` 在这个例子中,`queryData` 方法以非事务方式执行,避免了事务带来的开销,提高了查询操作的性能。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值