diff --git a/examples/example3/ChildProcess3.py b/examples/example3/ChildProcess3.py index 97c500b12b59d665ab767b3a599f189054a98279..402a19b1bce5d50e747266bb2f292b46aef0b97a 100644 --- a/examples/example3/ChildProcess3.py +++ b/examples/example3/ChildProcess3.py @@ -12,7 +12,7 @@ class ChildProcess3(cmp.CProcess): self.logger = None def postrun_init(self): - self.logger, self.logger_h = self.create_new_logger(f"{self.__class__.__name__}-({os.getpid()})") + self.logger = self.create_new_logger(f"{self.__class__.__name__}-({os.getpid()})") @cmp.CProcess.register_signal() def test_call(self, a): diff --git a/examples/example3/example3.py b/examples/example3/example3.py index a5836ea5f2d0ba9087545af6b032241a3ad20983..92a890e251fe9b7d876a69924c830e46b41f9608 100644 --- a/examples/example3/example3.py +++ b/examples/example3/example3.py @@ -24,8 +24,8 @@ class Form(QDialog): def __init__(self, parent=None): super().__init__(parent) - child_con = ChildProcessControl3(self, internal_log=False, internal_log_level=logging.INFO) - child_con.set_internal_log_level(logging.CRITICAL) + child_con = ChildProcessControl3(self, internal_log=True, internal_log_level=logging.INFO, log_file="log.log") + child_con.set_internal_log_level(logging.WARNING) child_con.mp_finished.connect(self.updateUI) diff --git a/src/cmp/CBase.py b/src/cmp/CBase.py index f0e96700fe557945c9808c6855d4462a06b571ce..49929e65482997a1aaceb5ff2b2f18130cdc1026 100644 --- a/src/cmp/CBase.py +++ b/src/cmp/CBase.py @@ -15,23 +15,35 @@ class CBase: def create_new_logger(self, logger_name: str, logger_handler: logging.Handler = None, - logger_format: str = " %(name)s %(message)s") -> (logging.Logger, logging.Handler): + logger_format: str = "%(asctime)s - %(name)s %(message)s", + to_file=None) -> (logging.Logger, logging.Handler): """ Creates a new logger with the given name and handler. If no handler is given, a RichHandler will be used. + :param logger_name: :param logger_handler: :param logger_format: + :param to_file: :return: """ if logger_handler is None: logger_handler = RichHandler(rich_tracebacks=True) - + logger_handler.setLevel(logging.DEBUG) _internal_logger = logging.getLogger(logger_name) _internal_logger.handlers = [logger_handler] _internal_logger.setLevel(logging.DEBUG) formatter = logging.Formatter(logger_format) logger_handler.setFormatter(formatter) - return _internal_logger, logger_handler + + if to_file is not None: + _file_handler = logging.FileHandler(to_file) + _file_handler.setLevel(logging.DEBUG) + _file_handler_formated = logging.Formatter(f"%(levelname)s > {logger_format})") + _file_handler.setFormatter(_file_handler_formated) + _internal_logger.addHandler(_file_handler) + + return _internal_logger + @property def internal_log_enabled(self): @@ -60,7 +72,7 @@ class CBase: @property def internal_log_level(self): - return self._internal_logger.level + return self._internal_logger.handlers[0].level @internal_log_level.setter def internal_log_level(self, level: int) -> None: @@ -82,7 +94,7 @@ class CBase: self._internal_logger.info(f"Internal log level of {self.__class__.__name__} has been set to CRITICAL.") else: self._internal_logger.info(f"Internal log level of {self.__class__.__name__} has been set to {level}.") - self._internal_logger.setLevel(level) + self._internal_logger.handlers[0].setLevel(level) else: raise Exception("Can't set internal log level. Internal logger not initialized") diff --git a/src/cmp/CProcess.py b/src/cmp/CProcess.py index 4024440fb69703c0d511ffff2661ed0c6c826895..d6165bbe761205468346a889e79b658c4d121c5a 100644 --- a/src/cmp/CProcess.py +++ b/src/cmp/CProcess.py @@ -19,7 +19,7 @@ class CProcess(CBase, Process): def __init__(self, state_queue: Queue, cmd_queue: Queue, kill_flag, - internal_log, internal_log_level, + internal_log, internal_log_level, log_file=None, *args, **kwargs): Process.__init__(self) @@ -27,6 +27,7 @@ class CProcess(CBase, Process): self._internal_log_level_ = internal_log_level self.logger = None self.logger_handler = None + self.log_file = log_file self.cmd_queue = cmd_queue self.state_queue = state_queue @@ -54,23 +55,23 @@ class CProcess(CBase, Process): def run(self): self.name = f"{os.getpid()}({self.name})" - self._internal_logger, self._internal_log_handler = self.create_new_logger( + self._internal_logger = self.create_new_logger( f"(cmp) {self.name}", - logger_handler=logging.handlers.QueueHandler(self.state_queue)) + logger_handler=logging.handlers.QueueHandler(self.state_queue), + logger_format="%(message)s") self.internal_log_enabled = self._internal_log_enabled_ self.internal_log_level = self._internal_log_level_ - self.logger, self.logger_handler = self.create_new_logger(f"{os.getpid()}({self.__class__.__name__})", - logger_handler=logging.handlers.QueueHandler( - self.state_queue)) - + self.logger = self.create_new_logger( + f"{os.getpid()}({self.__class__.__name__})", + logger_handler=logging.handlers.QueueHandler(self.state_queue)) self._internal_logger.debug(f"Child process {self.__class__.__name__} started.") - sys.stderr.write = self.logger.error - sys.stdout.write = self.logger.info + #sys.stderr.write = self.logger.error + #sys.stdout.write = self.logger.info self.postrun_init() @@ -103,7 +104,7 @@ class CProcess(CBase, Process): except Exception as e: self._internal_logger.warning(f"Received Exception {e}! Exiting Process {os.getpid()}") - self._internal_logger.debug(f"Child process monitor {self.__class__.__name__} ended.") + self._internal_logger.warning(f"Child process monitor {self.__class__.__name__} ended.") def __del__(self): #self.logger.warning(f"Child process {self.name} deleted.") @@ -128,7 +129,6 @@ class CProcess(CBase, Process): - @staticmethod def register_signal(postfix=None, signal_name: str = None): _postfix = postfix.strip() if postfix is not None else None @@ -171,6 +171,14 @@ class CProcess(CBase, Process): def set_internal_log_enabled(self, enabled): self.internal_log_enabled = enabled + @register_signal() + def set_child_log_level(self, level): + self.logger.setLevel(level) + + @register_signal() + def set_child_log_enabled(self, enabled): + self.logger.disabled = not enabled + @staticmethod def setter(signal_same: str = None): def register(func): diff --git a/src/cmp/CProcessControl.py b/src/cmp/CProcessControl.py index 1733ebc0215291d556bb7e9dc5115def10e637fe..865d7602e752a5631d21165deccbe0937675e21a 100644 --- a/src/cmp/CProcessControl.py +++ b/src/cmp/CProcessControl.py @@ -25,10 +25,20 @@ class CProcessControl(CBase, QObject): def __init__(self, parent: QObject = None, signal_class: QObject = None, internal_log: bool = False, - internal_log_level: int = logging.DEBUG): + internal_log_level: int = logging.DEBUG, + log_file: str = None): QObject.__init__(self, parent) CBase.__init__(self) - # self._kill_child_process_flag = kill_child_process_flag + self.log_file = log_file + self._internal_logger = self.create_new_logger( + f"(cmp) {self.name}", + to_file=self.log_file) + self.logger = self.create_new_logger( + f"{self.__class__.__name__}({os.getpid()})", + to_file=self.log_file) + self.internal_log_enabled = internal_log + self.internal_log_level = internal_log_level + if isinstance(parent, QWidget) or isinstance(parent, QWindow): parent.destroyed.connect(lambda: self.safe_exit(reason="Parent destroyed.")) @@ -57,10 +67,6 @@ class CProcessControl(CBase, QObject): self._child_kill_flag = Value('i', 1) - self._internal_logger, self._internal_log_handler = self.create_new_logger(f"(cmp) {self.name}") - self.internal_log_enabled = internal_log - 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() @@ -82,6 +88,7 @@ class CProcessControl(CBase, QObject): kill_flag=self._child_kill_flag, internal_log=self.internal_log_enabled, internal_log_level=self.internal_log_level, + log_file=self.log_file, *args, **kwargs) # self._child.register_kill_flag(self._child_kill_flag) self._child_process_pid = child.pid @@ -89,8 +96,6 @@ class CProcessControl(CBase, QObject): self._internal_logger.debug(f"Child process {self._child.name} created.") self.thread_manager.start(self._monitor_result_state) - - @property def child(self): return self._child @@ -213,6 +218,22 @@ class CProcessControl(CBase, QObject): def set_internal_log_enabled(self, enabled): self.internal_log_enabled = enabled + @register_function() + def set_child_log_level(self, level): + """ + Sets the regular logging level of the child process. + :param level: + :return: + """ + + @register_function() + def set_child_log_enabled(self, enabled): + """ + Enables or disables logging of the child process. + :param enabled: + :return: + """ + def safe_exit(self, reason: str = ""): self._internal_logger.warning(f"Shutting down ProcessControl {os.getpid()}. Reason: {reason}") self._child_kill_flag.value = 0