Python中logging模块StreamHandler与input()控制台输出顺序冲突问题
问题产生原因
这个问题和StreamHandler的执行速度无关,核心原因是两个独立输出流的缓冲刷新机制不同:
- logging模块的
StreamHandler()默认输出到标准错误流sys.stderr input()的提示文本默认输出到标准输出流sys.stdout
这两个流虽然最终都指向终端控制台,但各自拥有独立的缓冲区,默认的刷新触发条件不一致,就会导致输出顺序和代码执行顺序不符的情况。
修复方案
下面是几种常用的修复方式,可根据场景选择:
方案1:统一StreamHandler的输出流(最推荐)
直接将logging的StreamHandler输出指向和input相同的sys.stdout,让两者共用同一个缓冲区,从根源上避免顺序冲突。
修改configure_logger函数中StreamHandler的初始化代码即可:
import sys # 记得导入sys模块 # 替换原来的 stream_handler = logging.StreamHandler() stream_handler = logging.StreamHandler(stream=sys.stdout)
方案2:强制日志输出后立刻刷新缓冲区
如果不希望修改输出流,可以设置StreamHandler输出后立刻刷新缓冲区,Python 3.9及以上版本可以直接设置flushLevel参数:
stream_handler = logging.StreamHandler() stream_handler.flushLevel = logging.INFO # INFO及以上级别日志输出后立刻刷新
低版本Python可以在每次调用input之前,手动刷新两个流的缓冲区:
# 在所有input语句前加入以下两行 sys.stdout.flush() sys.stderr.flush() overwrite = input(f'Directory {directory} already exists. Overwrite? (y/n): ')
方案3:运行脚本时禁用全局缓冲
不需要修改代码,运行Python脚本时加上-u参数,强制stdout和stderr都使用无缓冲模式:
python -u your_script_name.py
该方案会略微降低输出性能,适合临时调试使用。
补充说明:你代码中的
overwrite.lower()没有生效,字符串是不可变类型,需要修改为overwrite = overwrite.lower()才能正确处理用户输入的大小写。
内容的提问来源于stack exchange,提问作者Not Dr Jeff
相关产品推荐
相关产品推荐

