""" ImageWorker와 메인 프로세스 간 로그 브리지 """ import threading import queue import logging import sys import os class LogBridge: """ImageWorker 프로세스의 로그를 메인 프로세스로 전달하는 브리지""" def __init__(self, main_logger, log_queue): self.main_logger = main_logger self.log_queue = log_queue self.reader_thread = None self.running = False def start(self): """로그 리더 스레드 시작""" if self.running: return self.running = True self.reader_thread = threading.Thread(target=self._log_reader, daemon=True) self.reader_thread.start() def stop(self): """로그 리더 스레드 중지""" self.running = False try: self.log_queue.put(None) # 종료 신호 except Exception: pass def _log_reader(self): """로그 큐에서 메시지를 읽어 메인 로거로 전달""" while self.running: try: log_record = self.log_queue.get(timeout=1) if log_record is None: # 종료 신호 break # 메인 로거로 전달 process_name = log_record.get('process_name', 'ImageWorker') level = log_record.get('level', logging.INFO) message = log_record.get('message', '') exc_info = log_record.get('exc_info', False) # 로그 브릿지를 통해 넘어오는 모든 메시지를 DEBUG 레벨로 처리 # 이렇게 하면 GUI에는 표시되지 않고 콘솔과 파일에만 기록됨 level = logging.DEBUG # 메시지에 프로세스 이름 추가 formatted_message = f"[{process_name}] {message}" # 메인 로거로 출력 if hasattr(self.main_logger, 'log'): self.main_logger.log(formatted_message, level=level, exc_info=exc_info) else: self.main_logger.log(level, formatted_message, exc_info=exc_info) except queue.Empty: continue except Exception as e: # 로그 처리 중 오류 발생 시 stderr로 출력 print(f"LogBridge 오류: {e}", file=sys.stderr) class ImageWorkerLogger: """ImageWorker에서 사용할 로거 (큐를 통해 메인 프로세스로 전송)""" def __init__(self, log_queue, process_name=None): self.log_queue = log_queue self.process_name = process_name or f"ImageWorker-{os.getpid()}" def log(self, message, level=logging.INFO, exc_info=False): """로그 메시지를 큐를 통해 메인 프로세스로 전송""" try: log_record = { 'process_name': self.process_name, 'level': level, 'message': str(message), 'exc_info': exc_info } self.log_queue.put(log_record) except Exception: # 큐 전송 실패 시 stderr로 출력 print(f"[{self.process_name}] {message}", file=sys.stderr) def debug(self, msg, *args, **kwargs): self.log(msg, logging.DEBUG) def info(self, msg, *args, **kwargs): self.log(msg, logging.INFO) def warning(self, msg, *args, **kwargs): self.log(msg, logging.WARNING) def error(self, msg, *args, **kwargs): exc_info = kwargs.get('exc_info', False) self.log(msg, logging.ERROR, exc_info=exc_info) def critical(self, msg, *args, **kwargs): self.log(msg, logging.CRITICAL)