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()
关键要点说明:
- 日志双输出配置:我在
setup_logging里用了handlers参数,同时添加FileHandler(写文件)和StreamHandler(输出到控制台),确保两边都能拿到日志。你原来的代码可能只配置了filename,明确配置双处理器会更稳妥。 - 捕获中断并记录:不管用哪种方案,核心都是主动捕获中断事件,然后调用
logging.info()或logging.warning()记录中断信息。 - 强制刷新日志:调用
logging.shutdown()会让所有日志处理器刷新缓冲区并关闭文件,这样就不会出现中断时日志没写入文件的情况了。
这样修改后,你再手动中断脚本,日志文件里就会清晰记录中断的时间和原因啦!
内容的提问来源于stack exchange,提问作者user8042669
相关产品推荐
相关产品推荐

