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

如何让Loguru在NSSM托管的Windows服务Python程序中正常工作?

Loguru文件日志在NSSM Windows服务中失效,且捕获的stdout含多余字符

问题现象

  • Python程序通过NSSM注册为Windows服务后,仅NSSM捕获的stdout日志生效,Loguru配置的TRACE级独立文件日志无法生成或写入;但直接在控制台运行程序时,Loguru可同时正常输出到文件和控制台。
  • NSSM捕获的stdout日志混入大量ANSI控制字符,可读性极差,示例日志:
[32m08:43:28[0m [1mINFO[0m [1mLogix write [36mInput_From_Word1[0m[1m      [32m0[0m[1m & [36mErsa_Input_From_Word2[0m[1m [32m8[0m[1m successful[0m
[32m08:43:28[0m [1mINFO[0m [1mLogix tags [36mOutput_To_Word1[0m[1m and     [36mRecipe_STRING[0m[1m unchanged
[32m08:43:28[0m[1m  INFO Skipping Click set([36mDS101[0m[1m,[36mDS300[0m[1m) to [32m0[0m[1m and [32m0844520[0m[1m[0m
[32m08:43:39[0m [1mINFO[0m [1mRead Logix tags [36mOutput_To_Word1[0m[1m[0m

当前Loguru配置

logger.remove()
# Setup the debug log file
logger.add(sink="file_{time}.log", 
    format="{time:HH:mm:ss} {level} {message}",  
    level="TRACE", rotation="25 MB", backtrace=True, diagnose=True, retention="7 days")
# Setup the debug to console
logger.add(sink=sys.stdout, colorize=True, 
    format="<green>{time:HH:mm:ss}</green> <level>{level}</level> <level>{message}</level>", 
    level="INFO")
# So we can have more colors in console window
logger = logger.opt(colors=True)

已尝试的无效方案

  • 将Loguru文件输出sink改为open("file_{time}.log", 'rw'),问题依旧
  • 修改NSSM服务账户为有权限的特定账户,服务无法启动;尝试将程序放在Public目录,服务也无法启动,目前保留在注册账户的目录下

需求

  • 实现Loguru的TRACE级独立文件日志在Windows服务中正常工作
  • 或让NSSM捕获的stdout日志不再包含多余控制字符

解决方法

一、修复Loguru文件日志失效问题

  1. 使用绝对路径指定日志文件
    服务运行时的工作目录通常不是程序所在目录,导致相对路径无法找到正确位置。修改日志文件路径为绝对路径:
import os
logger.add(
    sink=os.path.join(os.path.dirname(os.path.abspath(__file__)), "file_{time}.log"),
    format="{time:HH:mm:ss} {level} {message}",
    level="TRACE",
    rotation="25 MB",
    backtrace=True,
    diagnose=True,
    retention="7 days"
)
  1. 确保服务账户有日志目录读写权限
  • 若使用LocalSystem账户,默认对系统级目录权限充足,可将日志放在C:\ProgramData\你的程序名\logs这类目录,提前创建并赋予LocalSystem读写权限
  • 若使用自定义账户,确保该账户对程序目录及日志目录有完全控制权限
  1. 不要手动打开文件句柄
    Loguru的sink直接传入文件名时,会自动处理文件创建、轮转、权限等逻辑;手动用open()会破坏这些机制,且可能因服务环境下的文件句柄问题导致写入失败,因此必须改回直接传文件名的方式

二、清除stdout日志中的多余控制字符

  1. 根据运行环境动态关闭颜色输出
    服务运行时无交互式终端,无需颜色输出,可通过sys.stdout.isatty()判断环境,动态关闭颜色:
import sys
is_service = not sys.stdout.isatty()

logger.add(
    sink=sys.stdout,
    colorize=not is_service,
    format="{time:HH:mm:ss} {level} {message}" if is_service else "<green>{time:HH:mm:ss}</green> <level>{level}</level> <level>{message}</level>",
    level="INFO"
)
  1. 移除全局颜色优化
    若不需要全局颜色支持,可删除logger = logger.opt(colors=True),避免额外的ANSI字符输出

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 01:48:28