Spaces:
Sleeping
Sleeping
devjas1
(FEAT) add centralized error handling utilty for the polymer classification app: utils/error.py
177dc98
| """Centralized error handling utility for the polymer classification app. | |
| Provides consistent error logging and graceful UI error reporting""" | |
| import streamlit as st | |
| import traceback | |
| # Define a constant for error messages | |
| ERROR = "[ERROR]" | |
| class ErrorHandler: | |
| """Centralized error handler for the application""" | |
| def log_error(error: Exception, context: str = "", include_traceback: bool = False) -> None: | |
| """Log error to session state for display in UI""" | |
| if "log_messages" not in st.session_state: | |
| st.session_state["log_messages"] = [] | |
| error_msg = f"{ERROR} {context}: {str(error)}" if context else f"{ERROR} {str(error)}" | |
| if include_traceback: | |
| error_msg += f"\nTraceback: {traceback.format_exc()}" | |
| st.session_state["log_messages"].append(error_msg) | |
| def log_warning(message: str, context: str = "") -> None: | |
| """Log warning to session state""" | |
| if "log_messages" not in st.session_state: | |
| st.session_state["log_messages"] = [] | |
| warning_msg = f"[WARNING] {context}: {message}" if context else f"[WARNING] {message}" | |
| st.session_state["log_messages"].append(warning_msg) | |
| def log_info(message: str, context: str = "") -> None: | |
| """Log info message to session state""" | |
| if "log_messages" not in st.session_state: | |
| st.session_state["log_messages"] = [] | |
| info_msg = f"[INFO] {context}: {message}" if context else f"[INFO] {message}" | |
| st.session_state["log_messages"].append(info_msg) | |
| def handle_file_error(filename: str, error: Exception) -> str: | |
| """Handle file processing errors and return user-friendly message""" | |
| ErrorHandler.log_error(error, f"File processing: {filename}") | |
| if isinstance(error, FileNotFoundError): | |
| return f"β File not found: {filename}" | |
| elif isinstance(error, PermissionError): | |
| return f"β Permission denied accessing: {filename}" | |
| elif isinstance(error, (ValueError, TypeError)): | |
| return f"β Invalid file format in: {filename}. Please ensure it contains wavenumber and intensity columns." | |
| else: | |
| return f"β Error processing file: {filename}. {str(error)}" | |
| def handle_inference_error(model_name: str, error: Exception) -> str: | |
| """Handle model inference errors and return user-friendly message""" | |
| ErrorHandler.log_error(error, f"Model inference: {model_name}") | |
| if "CUDA" in str(error) or "device" in str(error).lower(): | |
| return f"β Device error with model {model_name}. Falling back to CPU." | |
| elif "shape" in str(error).lower() or "dimension" in str(error).lower(): | |
| return f"β Input shape mismatch for model {model_name}. Please check spectrum data format." | |
| else: | |
| return f"β Inference failed for model {model_name}: {str(error)}" | |
| def handle_parsing_error(filename: str, error: Exception) -> str: | |
| """Handle spectrum parsing errors and return user-friendly message""" | |
| ErrorHandler.log_error(error, f"Spectrum parsing: {filename}") | |
| if "could not convert" in str(error).lower(): | |
| return f"β Invalid data format in {filename}. Expected numeric wavenumber and intensity columns." | |
| elif "empty" in str(error).lower(): | |
| return f"β File {filename} appears to be empty or contains no valid data." | |
| elif "columns" in str(error).lower(): | |
| return f"β File {filename} must contain exactly 2 columns (wavenumber, intensity)." | |
| else: | |
| return f"β Failed to parse spectrum data from {filename}: {str(error)}" | |
| def clear_logs() -> None: | |
| """Clear all logged messages""" | |
| st.session_state["log_messages"] = [] | |
| def get_logs() -> list[str]: | |
| """Get all logged messages""" | |
| return st.session_state.get("log_messages", []) | |
| def display_error_ui(error_message: str, show_details: bool = False) -> None: | |
| """Display error in Streamlit UI with optional details""" | |
| st.error(error_message) | |
| if show_details and st.session_state.get("log_messages"): | |
| with st.expander("Error Details", expanded=False): | |
| for msg in st.session_state["log_messages"][-5:]: # Show last 5 log entries | |
| st.text(msg) | |
| def safe_execute(func, *args, error_context: str = "", show_error: bool = True, **kwargs): | |
| """ | |
| Safely execute a function with error handling | |
| Args: | |
| func: Function to execute | |
| *args: Arguments for the function | |
| error_context: Context description for error logging | |
| show_error: Whether to show error in UI | |
| **kwargs: Keyword arguments for the function | |
| Returns: | |
| Tuple of (result, success_flag) | |
| """ | |
| try: | |
| result = func(*args, **kwargs) | |
| return result, True | |
| except Exception as e: | |
| ErrorHandler.log_error(e, error_context) | |
| if show_error: | |
| error_msg = f"Error in {error_context}: {str(e)}" if error_context else str(e) | |
| st.error(error_msg) | |
| return None, False |