Skip to content
Snippets Groups Projects
Commit 71b16c97 authored by Christoph Schmidt's avatar Christoph Schmidt
Browse files

Updated to v0.2.0. Errors are now caught and displayed in the control thread.

parent 5c6e14a4
No related branches found
No related tags found
No related merge requests found
......@@ -28,3 +28,7 @@ class ChildProcess3(cmp.CProcess):
@test_call2.setter(emit_to='bar')
def test_call2(self, value: int):
self.my_value = value
@cmp.CProcess.register_signal()
def exception_call(self, value: int):
return value/0
\ No newline at end of file
......@@ -17,3 +17,6 @@ class ChildProcessControl3(cmp.CProcessControl):
print(a)
#print(f"{os.getpid()} -> call_without_mp with {a}, {b}, {c}!")
@cmp.CProcessControl.register_function()
def exception_call(self, a):
pass
......@@ -39,7 +39,7 @@ class Form(QDialog):
self.lineedit.setFocus()
self.setWindowTitle('Upper')
# self.lineedit.returnPressed.connect(lambda: child_con.call_without_mp(1, 2, c=3))
self.lineedit.returnPressed.connect(lambda: child_con.test_call(1))
self.lineedit.returnPressed.connect(lambda: child_con.exception_call(1))
def updateUI(self, text):
......
import traceback
class CException:
def __init__(self, parent_name: str, function_name: str, exception: Exception):
self.parent_name = parent_name
self.function_name: str = function_name
self.exception = exception
self.traceback_list: list[str] = traceback.format_exception(
type(self.exception),
value=self.exception,
tb=self.exception.__traceback__)
self.additional_info: str = ""
def traceback_short(self) -> str:
return "".join(self.traceback_list[-2:len(self.traceback_list)])
def traceback(self) -> str:
return "".join(self.traceback_list)
def set_additional_info(self, additional_info: str):
self.additional_info = additional_info
......@@ -118,6 +118,15 @@ class CProcess(CBase, Process):
result = cmp.CResultRecord(func_name, signal_name, res)
self.state_queue.put(result)
def _put_exception_to_queue(self, func_name, exc):
self._internal_logger.debug(f"Error executing {func_name}.")
tb_str = traceback.format_exception(type(exc), value=exc, tb=exc.__traceback__)
tb_join = "".join(tb_str[-2:len(tb_str)])
result = cmp.CException(self.name, func_name, exc, )
result.set_additional_info(tb_join)
self.state_queue.put(result)
@staticmethod
def register_signal(postfix=None, signal_name: str = None):
_postfix = postfix.strip() if postfix is not None else None
......@@ -138,9 +147,15 @@ class CProcess(CBase, Process):
self._internal_logger.debug(f"Constructing signal name for function '{func.__name__}': {sign}")
else:
sign = None
try:
res = func(self, *args, **kwargs)
self._put_result_to_queue(func_name, sign, res)
return res
except Exception as e:
self._internal_logger.error(f"Error in function {func_name}: {e} ({type(e)})")
self._put_exception_to_queue(func.__name__, e)
return None
return get_signature
......
......@@ -5,20 +5,23 @@ import os
import re
import signal
import time
import traceback
from multiprocessing import Queue, Process, Value
from typing import Type
from PySide6.QtCore import QObject, QThreadPool, Signal
from PySide6.QtGui import QWindow
from PySide6.QtWidgets import QWidget
from PySide6.QtWidgets import QWidget, QMessageBox
from rich.logging import RichHandler
import cmp
from cmp import CException
from cmp.CBase import CBase
class CProcessControl(CBase, QObject):
on_exception_raised = Signal(object, name='on_exception_raised')
def __init__(self, parent: QObject = None,
signal_class: QObject = None,
internal_log: bool = False,
......@@ -60,6 +63,9 @@ class CProcessControl(CBase, QObject):
self.internal_log_level = internal_log_level
self.logger, self.logger_handler = self.create_new_logger(f"{self.__class__.__name__}({os.getpid()})")
self.on_exception_raised.connect(self.display_exception)
self.msg_box = QMessageBox()
# ==================================================================================================================
#
# ==================================================================================================================
......@@ -107,6 +113,12 @@ class CProcessControl(CBase, QObject):
res.emit_signal(self._signal_class)
except Exception as e:
self._internal_logger.error(f"Error while emitting {res} in {self.__class__.__name__}: {e}")
elif isinstance(res, cmp.CException):
self._internal_logger.error(f"Received exception: {res}")
try:
self.on_exception_raised.emit(res)
except Exception as e:
self._internal_logger.error(f"Error while emitting exception: {e}")
else:
self._internal_logger.error(f"Received unknown result {res}!")
......@@ -118,6 +130,23 @@ class CProcessControl(CBase, QObject):
self.state_queue.close()
self.cmd_queue.close()
def display_exception(self, e: cmp.CException):
# Create a message box
try:
self.msg_box = QMessageBox()
self.msg_box.setIcon(QMessageBox.Critical)
self.msg_box.setText(f"Error executing {e.function_name} in {e.parent_name}")
self.msg_box.setInformativeText(f"Error: {e.exception}")
self.msg_box.setWindowTitle("Error")
self.msg_box.setDetailedText(e.traceback_short())
self.msg_box.setStandardButtons(QMessageBox.Ok)
self.msg_box.show()
self._internal_logger.error(f"Error executing {e.function_name} in {e.parent_name}: {e.exception}\n"
f"{e.traceback()}")
except Exception as e:
self._internal_logger.error(f"Error while displaying exception: {e}")
def execute_function(self, func: callable, signal: Signal = None):
self.register_function(signal)(func)(self)
......
......@@ -6,6 +6,7 @@ from rich.logging import RichHandler
from .CCommandRecord import CCommandRecord
from .CResultRecord import CResultRecord
from .CException import CException
from .CProcess import CProcess
from .CProcessControl import CProcessControl
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment