Files
shuidrop_gui/exe_file_logger.py
haosicheng 8ad02b4416 Todo: 集成多平台 解决PDD打包后js文件位置检索问题
Todo: 集成多平台 解决打包日志规划问题
Todo: 集成多平台 解决后端连接心跳与重连管理问题
2025-09-20 16:13:23 +08:00

129 lines
3.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
EXE文件日志器 - 将所有输出重定向到文件
适用于 pyinstaller -w 打包的exe
"""
import sys
import os
from datetime import datetime
import threading
class FileLogger:
"""文件日志器类"""
def __init__(self):
# 确定日志文件路径
if getattr(sys, 'frozen', False):
# 打包环境
self.log_dir = os.path.dirname(sys.executable)
else:
# 开发环境
self.log_dir = os.getcwd()
# 创建日志文件
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
self.log_file = os.path.join(self.log_dir, f"MultiPlatformGUI_{timestamp}.log")
# 线程锁,确保多线程写入安全
self.lock = threading.Lock()
# 初始化日志文件
self.write_log("=" * 80)
self.write_log("多平台客服GUI日志开始")
self.write_log(f"Python版本: {sys.version}")
self.write_log(f"是否打包环境: {getattr(sys, 'frozen', False)}")
self.write_log(f"日志文件: {self.log_file}")
self.write_log("=" * 80)
def write_log(self, message):
"""写入日志到文件"""
try:
with self.lock:
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
log_entry = f"[{timestamp}] {message}\n"
with open(self.log_file, 'a', encoding='utf-8') as f:
f.write(log_entry)
f.flush()
os.fsync(f.fileno()) # 强制写入磁盘
except Exception as e:
# 如果写入失败至少尝试输出到stderr
try:
sys.stderr.write(f"LOG_ERROR: {message} | Error: {e}\n")
sys.stderr.flush()
except:
pass
def write(self, text):
"""实现write方法以支持作为sys.stdout使用"""
if text.strip(): # 只记录非空内容
self.write_log(text.strip())
def flush(self):
"""实现flush方法"""
pass
class TeeOutput:
"""同时输出到原始输出和文件的类"""
def __init__(self, original, file_logger):
self.original = original
self.file_logger = file_logger
def write(self, text):
# 写入原始输出(如果存在)
if self.original:
try:
self.original.write(text)
self.original.flush()
except:
pass
# 写入文件日志
if text.strip():
self.file_logger.write_log(text.strip())
def flush(self):
if self.original:
try:
self.original.flush()
except:
pass
# 全局文件日志器实例
_file_logger = None
def setup_file_logging():
"""设置文件日志记录"""
global _file_logger
if _file_logger is None:
_file_logger = FileLogger()
# 保存原始的stdout和stderr
original_stdout = sys.stdout
original_stderr = sys.stderr
# 创建Tee输出同时输出到原始输出和文件
sys.stdout = TeeOutput(original_stdout, _file_logger)
sys.stderr = TeeOutput(original_stderr, _file_logger)
_file_logger.write_log("文件日志系统已设置完成")
return _file_logger
def log_to_file(message):
"""直接写入文件日志的函数"""
global _file_logger
if _file_logger:
_file_logger.write_log(message)
else:
# 如果还没有初始化,先初始化
setup_file_logging()
_file_logger.write_log(message)
# 注释掉自动初始化,改为手动调用
# if getattr(sys, 'frozen', False):
# setup_file_logging()