Spaces:
Sleeping
Sleeping
devjas1
commited on
Commit
Β·
177dc98
1
Parent(s):
566edf3
(FEAT) add centralized error handling utilty for the polymer classification app: utils/error.py
Browse filesImproves code maintainability and clarity
Lays groundwork for consistent error management across the project
- utils/errors.py +126 -0
utils/errors.py
CHANGED
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""Centralized error handling utility for the polymer classification app.
|
2 |
+
Provides consistent error logging and graceful UI error reporting"""
|
3 |
+
|
4 |
+
import streamlit as st
|
5 |
+
import traceback
|
6 |
+
|
7 |
+
# Define a constant for error messages
|
8 |
+
ERROR = "[ERROR]"
|
9 |
+
|
10 |
+
class ErrorHandler:
|
11 |
+
"""Centralized error handler for the application"""
|
12 |
+
|
13 |
+
@staticmethod
|
14 |
+
def log_error(error: Exception, context: str = "", include_traceback: bool = False) -> None:
|
15 |
+
"""Log error to session state for display in UI"""
|
16 |
+
if "log_messages" not in st.session_state:
|
17 |
+
st.session_state["log_messages"] = []
|
18 |
+
|
19 |
+
error_msg = f"{ERROR} {context}: {str(error)}" if context else f"{ERROR} {str(error)}"
|
20 |
+
|
21 |
+
if include_traceback:
|
22 |
+
error_msg += f"\nTraceback: {traceback.format_exc()}"
|
23 |
+
|
24 |
+
st.session_state["log_messages"].append(error_msg)
|
25 |
+
|
26 |
+
@staticmethod
|
27 |
+
def log_warning(message: str, context: str = "") -> None:
|
28 |
+
"""Log warning to session state"""
|
29 |
+
if "log_messages" not in st.session_state:
|
30 |
+
st.session_state["log_messages"] = []
|
31 |
+
|
32 |
+
warning_msg = f"[WARNING] {context}: {message}" if context else f"[WARNING] {message}"
|
33 |
+
st.session_state["log_messages"].append(warning_msg)
|
34 |
+
|
35 |
+
@staticmethod
|
36 |
+
def log_info(message: str, context: str = "") -> None:
|
37 |
+
"""Log info message to session state"""
|
38 |
+
if "log_messages" not in st.session_state:
|
39 |
+
st.session_state["log_messages"] = []
|
40 |
+
|
41 |
+
info_msg = f"[INFO] {context}: {message}" if context else f"[INFO] {message}"
|
42 |
+
st.session_state["log_messages"].append(info_msg)
|
43 |
+
|
44 |
+
@staticmethod
|
45 |
+
def handle_file_error(filename: str, error: Exception) -> str:
|
46 |
+
"""Handle file processing errors and return user-friendly message"""
|
47 |
+
ErrorHandler.log_error(error, f"File processing: {filename}")
|
48 |
+
|
49 |
+
if isinstance(error, FileNotFoundError):
|
50 |
+
return f"β File not found: {filename}"
|
51 |
+
elif isinstance(error, PermissionError):
|
52 |
+
return f"β Permission denied accessing: {filename}"
|
53 |
+
elif isinstance(error, (ValueError, TypeError)):
|
54 |
+
return f"β Invalid file format in: {filename}. Please ensure it contains wavenumber and intensity columns."
|
55 |
+
else:
|
56 |
+
return f"β Error processing file: {filename}. {str(error)}"
|
57 |
+
|
58 |
+
@staticmethod
|
59 |
+
def handle_inference_error(model_name: str, error: Exception) -> str:
|
60 |
+
"""Handle model inference errors and return user-friendly message"""
|
61 |
+
ErrorHandler.log_error(error, f"Model inference: {model_name}")
|
62 |
+
|
63 |
+
if "CUDA" in str(error) or "device" in str(error).lower():
|
64 |
+
return f"β Device error with model {model_name}. Falling back to CPU."
|
65 |
+
elif "shape" in str(error).lower() or "dimension" in str(error).lower():
|
66 |
+
return f"β Input shape mismatch for model {model_name}. Please check spectrum data format."
|
67 |
+
else:
|
68 |
+
return f"β Inference failed for model {model_name}: {str(error)}"
|
69 |
+
|
70 |
+
@staticmethod
|
71 |
+
def handle_parsing_error(filename: str, error: Exception) -> str:
|
72 |
+
"""Handle spectrum parsing errors and return user-friendly message"""
|
73 |
+
ErrorHandler.log_error(error, f"Spectrum parsing: {filename}")
|
74 |
+
|
75 |
+
if "could not convert" in str(error).lower():
|
76 |
+
return f"β Invalid data format in {filename}. Expected numeric wavenumber and intensity columns."
|
77 |
+
elif "empty" in str(error).lower():
|
78 |
+
return f"β File {filename} appears to be empty or contains no valid data."
|
79 |
+
elif "columns" in str(error).lower():
|
80 |
+
return f"β File {filename} must contain exactly 2 columns (wavenumber, intensity)."
|
81 |
+
else:
|
82 |
+
return f"β Failed to parse spectrum data from {filename}: {str(error)}"
|
83 |
+
|
84 |
+
@staticmethod
|
85 |
+
def clear_logs() -> None:
|
86 |
+
"""Clear all logged messages"""
|
87 |
+
st.session_state["log_messages"] = []
|
88 |
+
|
89 |
+
@staticmethod
|
90 |
+
def get_logs() -> list[str]:
|
91 |
+
"""Get all logged messages"""
|
92 |
+
return st.session_state.get("log_messages", [])
|
93 |
+
|
94 |
+
@staticmethod
|
95 |
+
def display_error_ui(error_message: str, show_details: bool = False) -> None:
|
96 |
+
"""Display error in Streamlit UI with optional details"""
|
97 |
+
st.error(error_message)
|
98 |
+
|
99 |
+
if show_details and st.session_state.get("log_messages"):
|
100 |
+
with st.expander("Error Details", expanded=False):
|
101 |
+
for msg in st.session_state["log_messages"][-5:]: # Show last 5 log entries
|
102 |
+
st.text(msg)
|
103 |
+
|
104 |
+
def safe_execute(func, *args, error_context: str = "", show_error: bool = True, **kwargs):
|
105 |
+
"""
|
106 |
+
Safely execute a function with error handling
|
107 |
+
|
108 |
+
Args:
|
109 |
+
func: Function to execute
|
110 |
+
*args: Arguments for the function
|
111 |
+
error_context: Context description for error logging
|
112 |
+
show_error: Whether to show error in UI
|
113 |
+
**kwargs: Keyword arguments for the function
|
114 |
+
|
115 |
+
Returns:
|
116 |
+
Tuple of (result, success_flag)
|
117 |
+
"""
|
118 |
+
try:
|
119 |
+
result = func(*args, **kwargs)
|
120 |
+
return result, True
|
121 |
+
except Exception as e:
|
122 |
+
ErrorHandler.log_error(e, error_context)
|
123 |
+
if show_error:
|
124 |
+
error_msg = f"Error in {error_context}: {str(e)}" if error_context else str(e)
|
125 |
+
st.error(error_msg)
|
126 |
+
return None, False
|