当stdout和stderr设为None时,Python logging模块为何仍能输出?
为什么设置sys.stdout/stderr为None后print失效但logging仍能输出?
先看测试脚本:
import logging import sys logging.basicConfig(level=logging.DEBUG) logging.info('This is a test for info') logging.error('This is a test for error') print('This is a test for print') sys.__stdout__ = None sys.stdout = None sys.__stderr__ = None sys.stderr = None logging.info('This is a test for info after setting stdout to None') logging.error('This is a test for error after setting stderr to None') print('This is a test for print after setting stdout to None')
输出结果:
INFO:root:This is a test for info ERROR:root:This is a test for error This is a test for print INFO:root:This is a test for info after setting stdout to None ERROR:root:This is a test for error after setting stderr to None
核心原因在于print和logging对标准流的依赖方式完全不同:
print的逻辑:
print函数默认直接使用当前sys.stdout这个Python对象,每次调用都会尝试调用它的write()方法输出内容。当你把sys.stdout设为None后,print找不到有效的输出对象,自然无法输出内容(实际内部会触发AttributeError,但Python会捕获这个错误并静默处理,所以你看不到报错,只是没输出)。logging的逻辑:
当你调用logging.basicConfig()时,logging模块会自动创建一个StreamHandler处理器,这个处理器在初始化时,会获取当时标准输出/错误流对应的底层文件描述符(比如终端的fd=1和fd=2),并持有这个句柄的引用。后续你修改sys.stdout和sys.stderr,只是改变了Python层面变量的指向,并不会影响logging已经持有的底层文件句柄——它依然能通过这个句柄直接往终端设备输出内容。
简单说:print是“实时依赖”sys模块的变量,而logging是“初始化时绑定”底层的实际输出设备,所以修改sys变量不会影响已经初始化好的logging。
内容的提问来源于stack exchange,提问作者LuckyCoder3607
相关产品推荐
相关产品推荐

