You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python logging.info二次运行生成空日志文件问题求助

解决Spyder中Python日志文件二次运行为空的问题

这个问题我太熟悉了——本质是logging模块的全局配置特性和Spyder/IPython的内核持久化机制在搞鬼!

问题根源

Spyder的IPython控制台默认会保持Python内核持续运行(除非你手动重启内核或关闭控制台标签)。第一次运行你的代码时,logging.basicConfig()会初始化根日志器,添加你指定的FileHandler和StreamHandler。但后续再次运行代码时,basicConfig()默认不会重新配置已初始化的日志系统(这是logging模块的设计逻辑:避免重复配置导致日志混乱),所以新创建的FileHandler根本没被添加到根日志器里——控制台的StreamHandler还在工作,所以你能看到输出,但新的日志文件因为没有处理器写入,自然是空的。

解决方案

根据你的需求(每次运行生成全新日志文件,不追加),给你几个可行的方案:

方案1:清理已有处理器后重新配置(最兼容你的Python版本)

在调用basicConfig()之前,先移除根日志器的所有已有处理器,确保每次运行都能加载新的配置。修改你的代码如下:

import logging
import datetime

starting_time = datetime.datetime.now()
logfilename = ('SomeLog' + datetime.datetime.now().strftime("%Y-%m-%d-%H-%M") + '.txt')
level = logging.INFO
format = ' %(message)s'

# 关键步骤:清除根日志器的所有已有处理器
root_logger = logging.getLogger()
for handler in root_logger.handlers[:]:
    root_logger.removeHandler(handler)
    handler.close()  # 关闭旧处理器,释放文件资源

handlers = [logging.FileHandler(logfilename, mode='w'), logging.StreamHandler()]
logging.basicConfig(level=level, format=format, handlers=handlers)

# 你的业务代码...
logging.info('Data written succesfully to: sqlite_table')
logging.info('Elapsed time to finish SQL write: ' + str((datetime.datetime.now() - starting_time).seconds) + ' seconds')
logging.info("Total elapsed time: " + str((datetime.datetime.now() - starting_time).seconds) + ' seconds')

logging.shutdown()

这里给FileHandler显式指定mode='w'(虽然默认就是写模式,但明确写出来更清晰),同时关闭旧处理器避免资源泄漏。

方案2:使用force=True参数(仅Python 3.8+适用)

如果你的Python版本是3.8或更高(注意你的Anaconda2019.03自带的是Python3.7,这个方法不适用),可以直接给basicConfig()加force=True参数,强制覆盖已有配置:

handlers = [logging.FileHandler(logfilename, mode='w'), logging.StreamHandler()]
logging.basicConfig(level=level, format=format, handlers=handlers, force=True)

方案3:手动创建独立日志器(更灵活的长期方案)

如果以后你的日志需求变复杂,推荐不要依赖根日志器,而是创建自己的日志器,完全控制配置逻辑:

import logging
import datetime

starting_time = datetime.datetime.now()
logfilename = ('SomeLog' + datetime.datetime.now().strftime("%Y-%m-%d-%H-%M") + '.txt')
level = logging.INFO
format = ' %(message)s'

# 创建自己的日志器
logger = logging.getLogger('MyAppLogger')
logger.setLevel(level)
# 清除已有处理器(防止重复添加)
for handler in logger.handlers[:]:
    logger.removeHandler(handler)
    handler.close()

# 添加文件处理器和控制台处理器
file_handler = logging.FileHandler(logfilename, mode='w')
file_handler.setFormatter(logging.Formatter(format))
stream_handler = logging.StreamHandler()
stream_handler.setFormatter(logging.Formatter(format))

logger.addHandler(file_handler)
logger.addHandler(stream_handler)

# 业务代码中用自己的日志器
logger.info('Data written succesfully to: sqlite_table')
logger.info('Elapsed time to finish SQL write: ' + str((datetime.datetime.now() - starting_time).seconds) + ' seconds')
logger.info("Total elapsed time: " + str((datetime.datetime.now() - starting_time).seconds) + ' seconds')

logging.shutdown()

额外提示

如果你不想每次改代码,也可以在Spyder中设置"每次运行前重启内核":点击运行按钮旁边的下拉菜单,选择"Run settings",勾选"Restart kernel before running"。但这样每次运行都会重新加载环境,速度会慢一点,适合简单脚本。

内容的提问来源于stack exchange,提问作者TomH

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:24:33