From b74cb96abad3b71fa16c2e4734aed37c90943ea1 Mon Sep 17 00:00:00 2001 From: Mars-ending <75156374+Mars-ending@users.noreply.github.com> Date: Fri, 17 Apr 2026 09:32:11 +0800 Subject: [PATCH] fix: resolve GBK encoding errors on Windows for Chinese content ## Problem On Windows systems with Chinese locale, Python's stdout uses GBK encoding by default. This causes UnicodeEncodeError when: 1. Model responses contain CJK characters or emoji 2. Logs are written to files via FileHandler without encoding specified Error example: 'gbk' codec can't encode character '\U0001f4d6' in position 1189 ## Changes 1. server_main.py: - Wrap sys.stdout/stderr with UTF-8 TextIOWrapper on Windows - Add encoding='utf-8' to FileHandler for server.log 2. utils/structured_logger.py: - Add encoding='utf-8' to FileHandler for workflow logs 3. utils/logger.py: - Wrap print() in try/except for UnicodeEncodeError fallback - On encoding error, strip problematic characters gracefully ## Testing Verified on Windows 11 with Chinese locale: - Workflow with Chinese task prompts now completes without encoding errors - Generated files correctly contain Unicode characters (CJK, emoji) --- Co-Authored-By: Claude --- server_main.py | 10 +++++++++- utils/logger.py | 17 +++++++++++------ utils/structured_logger.py | 3 ++- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/server_main.py b/server_main.py index c3418231cc..9549aa352e 100755 --- a/server_main.py +++ b/server_main.py @@ -1,7 +1,15 @@ import argparse import logging +import os +import sys from pathlib import Path +# Fix Windows stdout encoding before any logging +if sys.platform == 'win32': + import io + sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace') + sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='replace') + from runtime.bootstrap.schema import ensure_schema_registry_populated from server.app import app @@ -52,7 +60,7 @@ def main(): level=getattr(logging, args.log_level.upper()), format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", handlers=[ - logging.FileHandler(log_dir / "server.log"), + logging.FileHandler(log_dir / "server.log", encoding='utf-8'), logging.StreamHandler() ] ) diff --git a/utils/logger.py b/utils/logger.py index efe97c7ef5..73d6e7087e 100755 --- a/utils/logger.py +++ b/utils/logger.py @@ -104,12 +104,17 @@ def add_log(self, level: LogLevel, message: str = None, node_id: str = None, # Log to console if enabled if self.log_to_console: - print(f"[{timestamp}] [{level.value}] " - f"{f'Node {node_id} - ' if node_id else ''}" - f"{f'Event {event_type} - ' if event_type else ''}" - f"{message} " - f"{f'Details: {details} ' if details else ''}" - f"{f'Duration: {duration}' if duration else ''}") + try: + print(f"[{timestamp}] [{level.value}] " + f"{f'Node {node_id} - ' if node_id else ''}" + f"{f'Event {event_type} - ' if event_type else ''}" + f"{message} " + f"{f'Details: {details} ' if details else ''}" + f"{f'Duration: {duration}' if duration else ''}") + except UnicodeEncodeError: + # Fallback for Windows console with GBK encoding + fallback_msg = f"[{timestamp}] [{level.value}] {message}" + print(fallback_msg.encode('utf-8', errors='replace').decode('utf-8', errors='replace')) # Log using structured logger if enabled if self.use_structured_logging and self.structured_logger: diff --git a/utils/structured_logger.py b/utils/structured_logger.py index d3fc9be684..4ab953f23f 100755 --- a/utils/structured_logger.py +++ b/utils/structured_logger.py @@ -40,9 +40,10 @@ def __init__(self, name: str, log_level: LogLevel = LogLevel.INFO, log_file: str # Ensure log directory exists log_path = Path(log_file) log_path.parent.mkdir(parents=True, exist_ok=True) - handler = logging.FileHandler(log_file) + handler = logging.FileHandler(log_file, encoding='utf-8') else: handler = logging.StreamHandler(sys.stdout) + handler.terminator = '' # Prevent newline issues handler.setFormatter(formatter) self.logger.addHandler(handler)