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

Python脚本手动中断后控制台日志未写入日志文件的解决方法

这个问题我之前也碰到过!其实原因很简单:当你在PyCharm里按Ctrl+C中断脚本时,Python会抛出KeyboardInterrupt异常,但默认情况下logging模块不会自动捕获并记录这个异常——而且脚本被强制中断时,日志缓冲区里的内容可能还没来得及写入文件就直接退出了。

下面给你两种靠谱的解决方案,都能让中断信息同步写到日志文件里:

方案一:直接捕获KeyboardInterrupt异常(简单直观)

这种方式不需要额外处理信号,直接用try-except包裹主循环,捕获中断后手动记录日志,最后确保日志写入文件:

import logging
import os
import sys
import time

def setup_logging():
    my_log_file_name = os.path.basename(__file__) + ".my_log"
    # 配置日志同时输出到文件和控制台
    logging.basicConfig(
        level=logging.INFO,
        format='%(asctime)s,%(msecs)03d %(name)s %(levelname)s %(message)s',
        handlers=[
            logging.FileHandler(my_log_file_name, mode='a'),
            logging.StreamHandler(sys.stdout)
        ]
    )

def main():
    setup_logging()
    logging.info("脚本启动,开始无限循环...")
    try:
        while True:
            # 这里放你的业务逻辑,比如每隔1秒输出一条日志
            logging.info("循环运行中...")
            time.sleep(1)
    except KeyboardInterrupt:
        # 捕获用户中断,记录日志
        logging.info("脚本被用户手动中断(Ctrl+C)")
    except Exception as e:
        # 处理其他意外异常
        logging.error(f"脚本运行出错: {str(e)}", exc_info=True)
    finally:
        # 无论是否异常,都确保日志缓冲区内容写入文件
        logging.shutdown()
        sys.exit(0)

if __name__ == "__main__":
    main()

方案二:通过信号处理捕获中断(更灵活,支持其他终止信号)

如果你需要处理更多终止信号(比如系统发送的SIGTERM),可以用signal模块注册信号处理函数,这种方式更通用:

import logging
import os
import sys
import time
import signal

def setup_logging():
    my_log_file_name = os.path.basename(__file__) + ".my_log"
    logging.basicConfig(
        level=logging.INFO,
        format='%(asctime)s,%(msecs)03d %(name)s %(levelname)s %(message)s',
        handlers=[
            logging.FileHandler(my_log_file_name, mode='a'),
            logging.StreamHandler(sys.stdout)
        ]
    )

def handle_interrupt(signum, frame):
    # 处理中断信号(比如SIGINT就是Ctrl+C)
    signal_name = signal.Signals(signum).name
    logging.info(f"脚本被中断,信号类型: {signal_name}")
    # 强制刷新日志缓冲区,确保写入文件
    logging.shutdown()
    sys.exit(0)

def main():
    setup_logging()
    # 注册SIGINT(Ctrl+C)和SIGTERM(系统终止信号)的处理函数
    signal.signal(signal.SIGINT, handle_interrupt)
    signal.signal(signal.SIGTERM, handle_interrupt)
    
    logging.info("脚本启动,开始无限循环...")
    try:
        while True:
            logging.info("循环运行中...")
            time.sleep(1)
    except Exception as e:
        logging.error(f"脚本运行出错: {str(e)}", exc_info=True)
        logging.shutdown()
        sys.exit(1)

if __name__ == "__main__":
    main()

关键要点说明:

  1. 日志双输出配置:我在setup_logging里用了handlers参数,同时添加FileHandler(写文件)和StreamHandler(输出到控制台),确保两边都能拿到日志。你原来的代码可能只配置了filename,明确配置双处理器会更稳妥。
  2. 捕获中断并记录:不管用哪种方案,核心都是主动捕获中断事件,然后调用logging.info()或logging.warning()记录中断信息。
  3. 强制刷新日志:调用logging.shutdown()会让所有日志处理器刷新缓冲区并关闭文件,这样就不会出现中断时日志没写入文件的情况了。

这样修改后,你再手动中断脚本,日志文件里就会清晰记录中断的时间和原因啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:32:25