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

Pythonic方式实现bot.py与keepalive.py的日志共享配置

Pythonic方式在bot.py和keepalive.py之间共享日志记录器

这个问题其实挺典型的——你之前尝试传递logger实例的思路走不通,核心原因是:当keepalive用subprocess重启bot时,会启动一个全新的Python进程,两个进程的内存空间完全隔离,根本没法直接传递内存中的对象。

正确的Pythonic做法是利用logging模块的原生设计:它的logger是按名称层级全局注册的,咱们只需要做集中式的日志配置,让两个脚本(包括重启后的bot进程)都加载相同的日志规则,就能实现统一的日志输出。

步骤1:创建公共日志配置模块

先写一个单独的log_config.py,把所有日志相关的配置(级别、格式、输出目标)都集中在这里,这样bot和keepalive都能复用:

import logging
from logging.handlers import RotatingFileHandler
import sys

def setup_logger(name="bot_system"):
    # 获取指定名称的logger(全局唯一)
    logger = logging.getLogger(name)
    logger.setLevel(logging.INFO)

    # 避免重复添加处理器(比如多次调用setup_logger时)
    if logger.handlers:
        return logger

    # 定义日志格式:包含时间、logger名称、进程ID、级别、内容
    formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(process)d - %(levelname)s - %(message)s'
    )

    # 控制台输出处理器
    console_handler = logging.StreamHandler(sys.stdout)
    console_handler.setFormatter(formatter)
    logger.addHandler(console_handler)

    # 文件输出处理器(按大小分割,避免日志文件过大)
    file_handler = RotatingFileHandler(
        'bot_system.log',
        maxBytes=5*1024*1024,  # 5MB
        backupCount=3,          # 保留3个备份
        encoding='utf-8'
    )
    file_handler.setFormatter(formatter)
    logger.addHandler(file_handler)

    return logger

步骤2:在bot.py中使用日志

直接导入公共配置,获取logger即可——不管是直接运行bot,还是被keepalive启动,都会加载相同的日志规则:

from log_config import setup_logger

# 获取bot专属的logger(指定名称方便区分日志来源)
logger = setup_logger("bot")

def main():
    logger.info("Bot 启动成功!")
    # 这里写你的bot核心逻辑
    # 比如监听某个套接字端口,供keepalive检测
    # ...

if __name__ == "__main__":
    main()

步骤3:在keepalive.py中使用日志

同样导入公共配置,获取keepalive专属的logger,这样日志里能清晰区分是keepalive还是bot的输出:

import subprocess
import time
import socket
from log_config import setup_logger

# 获取keepalive专属的logger
logger = setup_logger("keepalive")

# 配置bot的检测参数
BOT_CHECK_PORT = 12345  # bot需要监听这个端口,供keepalive检测
BOT_START_CMD = ["python", "bot.py"]

def is_bot_alive():
    """检测bot是否存活(通过套接字连接)"""
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(5)
        # 尝试连接bot的监听端口
        connect_result = sock.connect_ex(('localhost', BOT_CHECK_PORT))
        sock.close()
        return connect_result == 0
    except Exception as e:
        logger.error(f"检测bot存活时出错:{str(e)}")
        return False

def restart_bot():
    """重启bot进程"""
    logger.warning("Bot 已离线,正在重启...")
    # 可选:杀掉残留的bot进程(根据实际情况处理)
    # ...
    # 启动新的bot进程
    subprocess.Popen(BOT_START_CMD)
    logger.info("Bot 重启完成")

def main():
    logger.info("Keepalive 服务启动,开始监控bot状态")
    while True:
        if not is_bot_alive():
            restart_bot()
        # 每小时检测一次
        time.sleep(3600)

if __name__ == "__main__":
    main()

为什么这是Pythonic的?

  1. 符合logging模块的设计哲学:logger是全局注册的,相同名称的logger在同一个进程中是单例,不同进程通过加载相同配置保证日志规则一致。
  2. 遵循DRY原则:日志配置只写一次,所有脚本复用,避免重复代码。
  3. 解决进程隔离问题:重启后的bot进程会重新加载日志配置,不需要传递任何内存对象,完美适配keepalive的重启场景。

额外优化建议

  • 如果需要更灵活的配置(比如不同环境用不同日志级别),可以用logging.config.dictConfig把配置写成字典,或者用fileConfig从配置文件加载。
  • 日志格式里的%(process)d(进程ID)能帮你快速区分不同bot进程的日志。
  • 可以根据需求调整日志轮转的大小和备份数量,避免日志文件占用过多磁盘空间。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:05:23