Skip to main content
Glama
sumik5
by sumik5
error_handler.py11.6 kB
""" エラーハンドリングモジュール SRT翻訳システムの例外クラスとエラー処理機能を提供します。 """ import logging import traceback import datetime from typing import Dict, Optional, Any class SRTTranslationError(Exception): """SRT翻訳システムの基底例外クラス""" def __init__(self, message: str, error_code: str = None, context: Dict[str, Any] = None): """ 初期化 Args: message: エラーメッセージ error_code: エラーコード context: エラーコンテキスト情報 """ super().__init__(message) self.message = message self.error_code = error_code or self.__class__.__name__ self.context = context or {} self.timestamp = datetime.datetime.now() class SRTParseError(SRTTranslationError): """SRT解析エラー""" def __init__(self, message: str, line_number: int = None, file_path: str = None): """ SRT解析エラーの初期化 Args: message: エラーメッセージ line_number: エラーが発生した行番号 file_path: エラーが発生したファイルパス """ context = {} if line_number is not None: context['line_number'] = line_number if file_path: context['file_path'] = file_path super().__init__(message, "SRT_PARSE_ERROR", context) class TranslationError(SRTTranslationError): """翻訳処理エラー""" def __init__(self, message: str, model_name: str = None, api_response: str = None): """ 翻訳処理エラーの初期化 Args: message: エラーメッセージ model_name: 使用していたモデル名 api_response: API応答内容 """ context = {} if model_name: context['model_name'] = model_name if api_response: context['api_response'] = api_response super().__init__(message, "TRANSLATION_ERROR", context) class APIConnectionError(SRTTranslationError): """API接続エラー""" def __init__(self, message: str, url: str = None, status_code: int = None, timeout: float = None): """ API接続エラーの初期化 Args: message: エラーメッセージ url: 接続先URL status_code: HTTPステータスコード timeout: タイムアウト時間 """ context = {} if url: context['url'] = url if status_code is not None: context['status_code'] = status_code if timeout is not None: context['timeout'] = timeout super().__init__(message, "API_CONNECTION_ERROR", context) class FileError(SRTTranslationError): """ファイル操作エラー""" def __init__(self, message: str, file_path: str = None, operation: str = None): """ ファイル操作エラーの初期化 Args: message: エラーメッセージ file_path: 操作対象ファイルパス operation: 実行していた操作 """ context = {} if file_path: context['file_path'] = file_path if operation: context['operation'] = operation super().__init__(message, "FILE_ERROR", context) class ErrorHandler: """エラー処理クラス""" def __init__(self, logger_name: str = __name__): """ 初期化 Args: logger_name: ロガー名 """ self.logger = logging.getLogger(logger_name) def log_error(self, error: Exception, context: Dict[str, Any] = None) -> None: """ エラーをログに記録 Args: error: ログに記録する例外 context: 追加のコンテキスト情報 """ try: # エラー情報の収集 error_info = { 'error_type': error.__class__.__name__, 'error_message': str(error), 'timestamp': datetime.datetime.now().isoformat(), } # SRTTranslationErrorの場合は追加情報を含める if isinstance(error, SRTTranslationError): error_info.update({ 'error_code': error.error_code, 'error_context': error.context, }) # 追加コンテキストがある場合は含める if context: error_info['additional_context'] = context # スタックトレースを取得 stack_trace = traceback.format_exc() error_info['stack_trace'] = stack_trace # ログレベルに応じて記録 if isinstance(error, (APIConnectionError, FileError)): self.logger.error(f"重大なエラー: {error_info}") elif isinstance(error, (SRTParseError, TranslationError)): self.logger.warning(f"処理エラー: {error_info}") else: self.logger.error(f"未知のエラー: {error_info}") except Exception as log_error: # ログ記録自体がエラーになった場合の対処 self.logger.critical(f"ログ記録中にエラーが発生: {str(log_error)}") self.logger.critical(f"元のエラー: {str(error)}") def format_user_message(self, error: Exception) -> str: """ ユーザー向けエラーメッセージ生成 Args: error: フォーマット対象の例外 Returns: str: ユーザー向けのエラーメッセージ """ try: if isinstance(error, SRTParseError): base_message = "SRTファイルの解析に失敗しました。" if 'line_number' in error.context: base_message += f" (行番号: {error.context['line_number']})" if 'file_path' in error.context: base_message += f" (ファイル: {error.context['file_path']})" return base_message elif isinstance(error, TranslationError): base_message = "翻訳処理に失敗しました。" if 'model_name' in error.context: base_message += f" 使用モデル: {error.context['model_name']}" return base_message elif isinstance(error, APIConnectionError): base_message = "APIへの接続に失敗しました。" if 'url' in error.context: base_message += f" 接続先: {error.context['url']}" if 'status_code' in error.context: base_message += f" (ステータスコード: {error.context['status_code']})" return base_message elif isinstance(error, FileError): base_message = "ファイル操作に失敗しました。" if 'file_path' in error.context: base_message += f" ファイル: {error.context['file_path']}" if 'operation' in error.context: base_message += f" (操作: {error.context['operation']})" return base_message elif isinstance(error, SRTTranslationError): return f"処理中にエラーが発生しました: {error.message}" else: return f"予期しないエラーが発生しました: {str(error)}" except Exception: return "エラーメッセージの生成に失敗しました。システム管理者にお問い合わせください。" def handle_error(self, error: Exception, context: Dict[str, Any] = None) -> str: """ エラーの総合的な処理 Args: error: 処理対象の例外 context: 追加のコンテキスト情報 Returns: str: ユーザー向けメッセージ """ # エラーをログに記録 self.log_error(error, context) # ユーザー向けメッセージを生成して返す return self.format_user_message(error) @staticmethod def create_context(operation: str = None, file_path: str = None, line_number: int = None, **kwargs) -> Dict[str, Any]: """ コンテキスト情報を作成 Args: operation: 実行中の操作 file_path: 処理中のファイルパス line_number: 処理中の行番号 **kwargs: その他の情報 Returns: Dict[str, Any]: コンテキスト辞書 """ context = {} if operation: context['operation'] = operation if file_path: context['file_path'] = file_path if line_number is not None: context['line_number'] = line_number # 追加の情報があれば含める context.update(kwargs) return context # 基本テスト機能 def _basic_error_handling_test(): """基本的なエラーハンドリング機能のテスト""" # ログ設定 logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s') error_handler = ErrorHandler() # SRTParseErrorのテスト parse_error = SRTParseError("無効なタイムスタンプ形式", line_number=5, file_path="test.srt") user_msg = error_handler.format_user_message(parse_error) print(f"SRTParseError: {user_msg}") assert "行番号: 5" in user_msg assert "test.srt" in user_msg # TranslationErrorのテスト translation_error = TranslationError("翻訳APIの応答が異常", model_name="llama-3-8b") user_msg = error_handler.format_user_message(translation_error) print(f"TranslationError: {user_msg}") assert "llama-3-8b" in user_msg # APIConnectionErrorのテスト api_error = APIConnectionError("接続タイムアウト", url="http://localhost:1234", timeout=30.0) user_msg = error_handler.format_user_message(api_error) print(f"APIConnectionError: {user_msg}") assert "localhost:1234" in user_msg # FileErrorのテスト file_error = FileError("ファイルが見つかりません", file_path="input.srt", operation="読み込み") user_msg = error_handler.format_user_message(file_error) print(f"FileError: {user_msg}") assert "input.srt" in user_msg assert "読み込み" in user_msg # コンテキスト作成テスト context = ErrorHandler.create_context( operation="翻訳", file_path="test.srt", line_number=10, model_name="llama-3-8b" ) assert context['operation'] == "翻訳" assert context['model_name'] == "llama-3-8b" print("✓ コンテキスト作成テスト成功") print("全てのエラーハンドリングテストが成功しました") if __name__ == "__main__": # 基本テスト実行 _basic_error_handling_test()

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/sumik5/translate-srt-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server