From 5d49063b263998255981d58c4f6fe2c8d5abe720 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=88=92=E9=85=92=E7=9A=84=E6=9D=8E=E7=99=BD?= <670939375@qq.com> Date: Sun, 24 Aug 2025 15:41:58 +0800 Subject: [PATCH] Communication encoding bug fixed, all converted to UTF-8. --- .../insight_engine_streamlit_app.py | 14 +++ SingleEngineApp/media_engine_streamlit_app.py | 14 +++ SingleEngineApp/query_engine_streamlit_app.py | 14 +++ app.py | 90 ++++++++++++++++--- templates/index.html | 52 ++++++++++- 5 files changed, 170 insertions(+), 14 deletions(-) diff --git a/SingleEngineApp/insight_engine_streamlit_app.py b/SingleEngineApp/insight_engine_streamlit_app.py index 283ad8c..6e86374 100644 --- a/SingleEngineApp/insight_engine_streamlit_app.py +++ b/SingleEngineApp/insight_engine_streamlit_app.py @@ -8,6 +8,20 @@ import sys import streamlit as st from datetime import datetime import json +import locale + +# 设置UTF-8编码环境 +os.environ['PYTHONIOENCODING'] = 'utf-8' +os.environ['PYTHONUTF8'] = '1' + +# 设置系统编码 +try: + locale.setlocale(locale.LC_ALL, 'en_US.UTF-8') +except locale.Error: + try: + locale.setlocale(locale.LC_ALL, 'C.UTF-8') + except locale.Error: + pass # 添加src目录到Python路径 sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) diff --git a/SingleEngineApp/media_engine_streamlit_app.py b/SingleEngineApp/media_engine_streamlit_app.py index e3ea093..5791458 100644 --- a/SingleEngineApp/media_engine_streamlit_app.py +++ b/SingleEngineApp/media_engine_streamlit_app.py @@ -8,6 +8,20 @@ import sys import streamlit as st from datetime import datetime import json +import locale + +# 设置UTF-8编码环境 +os.environ['PYTHONIOENCODING'] = 'utf-8' +os.environ['PYTHONUTF8'] = '1' + +# 设置系统编码 +try: + locale.setlocale(locale.LC_ALL, 'en_US.UTF-8') +except locale.Error: + try: + locale.setlocale(locale.LC_ALL, 'C.UTF-8') + except locale.Error: + pass # 添加src目录到Python路径 sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) diff --git a/SingleEngineApp/query_engine_streamlit_app.py b/SingleEngineApp/query_engine_streamlit_app.py index 2d9b1e5..bcf4869 100644 --- a/SingleEngineApp/query_engine_streamlit_app.py +++ b/SingleEngineApp/query_engine_streamlit_app.py @@ -8,6 +8,20 @@ import sys import streamlit as st from datetime import datetime import json +import locale + +# 设置UTF-8编码环境 +os.environ['PYTHONIOENCODING'] = 'utf-8' +os.environ['PYTHONUTF8'] = '1' + +# 设置系统编码 +try: + locale.setlocale(locale.LC_ALL, 'en_US.UTF-8') +except locale.Error: + try: + locale.setlocale(locale.LC_ALL, 'C.UTF-8') + except locale.Error: + pass # 添加src目录到Python路径 sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) diff --git a/app.py b/app.py index 5291cd8..cfd8e56 100644 --- a/app.py +++ b/app.py @@ -15,16 +15,26 @@ from flask_socketio import SocketIO, emit import signal import atexit import requests +import logging +from pathlib import Path app = Flask(__name__) app.config['SECRET_KEY'] = 'weibo_analysis_system_2024' socketio = SocketIO(app, cors_allowed_origins="*") +# 设置UTF-8编码环境 +os.environ['PYTHONIOENCODING'] = 'utf-8' +os.environ['PYTHONUTF8'] = '1' + +# 创建日志目录 +LOG_DIR = Path('logs') +LOG_DIR.mkdir(exist_ok=True) + # 全局变量存储进程信息 processes = { - 'insight': {'process': None, 'port': 8501, 'status': 'stopped', 'output': []}, - 'media': {'process': None, 'port': 8502, 'status': 'stopped', 'output': []}, - 'query': {'process': None, 'port': 8503, 'status': 'stopped', 'output': []} + 'insight': {'process': None, 'port': 8501, 'status': 'stopped', 'output': [], 'log_file': None}, + 'media': {'process': None, 'port': 8502, 'status': 'stopped', 'output': [], 'log_file': None}, + 'query': {'process': None, 'port': 8503, 'status': 'stopped', 'output': [], 'log_file': None} } # 输出队列 @@ -34,8 +44,36 @@ output_queues = { 'query': Queue() } +def write_log_to_file(app_name, line): + """将日志写入文件""" + try: + log_file_path = LOG_DIR / f"{app_name}.log" + with open(log_file_path, 'a', encoding='utf-8') as f: + f.write(line + '\n') + f.flush() + except Exception as e: + print(f"Error writing log for {app_name}: {e}") + +def read_log_from_file(app_name, tail_lines=None): + """从文件读取日志""" + try: + log_file_path = LOG_DIR / f"{app_name}.log" + if not log_file_path.exists(): + return [] + + with open(log_file_path, 'r', encoding='utf-8') as f: + lines = f.readlines() + lines = [line.rstrip('\n\r') for line in lines if line.strip()] + + if tail_lines: + return lines[-tail_lines:] + return lines + except Exception as e: + print(f"Error reading log for {app_name}: {e}") + return [] + def read_process_output(process, app_name): - """读取进程输出并放入队列""" + """读取进程输出并写入文件""" while True: try: if process.poll() is not None: @@ -43,15 +81,14 @@ def read_process_output(process, app_name): output = process.stdout.readline() if output: - line = output.decode('utf-8', errors='ignore').strip() + # 使用UTF-8解码,忽略错误字符 + line = output.decode('utf-8', errors='replace').strip() if line: timestamp = datetime.now().strftime('%H:%M:%S') formatted_line = f"[{timestamp}] {line}" - # 添加到输出列表(保持最近100行) - processes[app_name]['output'].append(formatted_line) - if len(processes[app_name]['output']) > 100: - processes[app_name]['output'].pop(0) + # 写入日志文件 + write_log_to_file(app_name, formatted_line) # 发送到前端 socketio.emit('console_output', { @@ -59,7 +96,9 @@ def read_process_output(process, app_name): 'line': formatted_line }) except Exception as e: - print(f"Error reading output for {app_name}: {e}") + error_msg = f"Error reading output for {app_name}: {e}" + print(error_msg) + write_log_to_file(app_name, f"[{datetime.now().strftime('%H:%M:%S')}] {error_msg}") break def start_streamlit_app(app_name, script_path, port): @@ -72,6 +111,15 @@ def start_streamlit_app(app_name, script_path, port): if not os.path.exists(script_path): return False, f"文件不存在: {script_path}" + # 清空之前的日志文件 + log_file_path = LOG_DIR / f"{app_name}.log" + if log_file_path.exists(): + log_file_path.unlink() + + # 创建启动日志 + start_msg = f"[{datetime.now().strftime('%H:%M:%S')}] 启动 {app_name} 应用..." + write_log_to_file(app_name, start_msg) + cmd = [ sys.executable, '-m', 'streamlit', 'run', script_path, @@ -81,6 +129,15 @@ def start_streamlit_app(app_name, script_path, port): '--logger.level', 'info' ] + # 设置环境变量确保UTF-8编码 + env = os.environ.copy() + env.update({ + 'PYTHONIOENCODING': 'utf-8', + 'PYTHONUTF8': '1', + 'LANG': 'en_US.UTF-8', + 'LC_ALL': 'en_US.UTF-8' + }) + # 使用当前工作目录而不是脚本目录 process = subprocess.Popen( cmd, @@ -88,7 +145,9 @@ def start_streamlit_app(app_name, script_path, port): stderr=subprocess.STDOUT, bufsize=1, universal_newlines=False, - cwd=os.getcwd() + cwd=os.getcwd(), + env=env, + encoding=None # 让我们手动处理编码 ) processes[app_name]['process'] = process @@ -106,7 +165,9 @@ def start_streamlit_app(app_name, script_path, port): return True, f"{app_name} 应用启动中..." except Exception as e: - return False, f"启动失败: {str(e)}" + error_msg = f"启动失败: {str(e)}" + write_log_to_file(app_name, f"[{datetime.now().strftime('%H:%M:%S')}] {error_msg}") + return False, error_msg def stop_streamlit_app(app_name): """停止Streamlit应用""" @@ -245,9 +306,12 @@ def get_output(app_name): if app_name not in processes: return jsonify({'success': False, 'message': '未知应用'}) + # 从文件读取完整日志 + output_lines = read_log_from_file(app_name) + return jsonify({ 'success': True, - 'output': processes[app_name]['output'] + 'output': output_lines }) @app.route('/api/search', methods=['POST']) diff --git a/templates/index.html b/templates/index.html index b8842d3..b4638fe 100644 --- a/templates/index.html +++ b/templates/index.html @@ -338,6 +338,11 @@ checkStatus(); setInterval(checkStatus, 5000); + // 定期刷新控制台输出 + setInterval(() => { + refreshConsoleOutput(); + }, 2000); + // 延迟预加载iframe以确保应用启动完成 setTimeout(() => { preloadIframes(); @@ -446,12 +451,18 @@ // 清空并加载新的控制台输出 document.getElementById('consoleOutput').innerHTML = '