From 7016138c849a4f8d0b4d296b319e0b23a1b7bd9e Mon Sep 17 00:00:00 2001 From: allegroai <> Date: Sun, 27 Nov 2022 17:32:24 +0200 Subject: [PATCH] Fix ClearML SDK does not work with PyTest (related to https://github.com/pytest-dev/pytest/issues/5502#issuecomment-647157873) --- clearml/backend_interface/logger.py | 30 ++++++++++++++++++----------- clearml/task.py | 12 ++++++++++++ 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/clearml/backend_interface/logger.py b/clearml/backend_interface/logger.py index 0fe69304..bd14c3f0 100644 --- a/clearml/backend_interface/logger.py +++ b/clearml/backend_interface/logger.py @@ -19,10 +19,10 @@ class StdStreamPatch(object): (not running_remotely() or DEBUG_SIMULATE_REMOTE_TASK.get()): StdStreamPatch._stdout_proxy = PrintPatchLogger( sys.stdout, a_logger, level=logging.INFO, load_config_defaults=load_config_defaults) \ - if connect_stdout else None + if connect_stdout and not sys.stdout.closed else None StdStreamPatch._stderr_proxy = PrintPatchLogger( sys.stderr, a_logger, level=logging.ERROR, load_config_defaults=load_config_defaults) \ - if connect_stderr else None + if connect_stderr and not sys.stderr.closed else None if StdStreamPatch._stdout_proxy: # noinspection PyBroadException @@ -199,11 +199,15 @@ class PrintPatchLogger(object): self._test_lr_flush() self.lock.acquire() - with PrintPatchLogger.recursion_protect_lock: - if hasattr(self._terminal, '_original_write'): - self._terminal._original_write(message) # noqa - else: - self._terminal.write(message) + # noinspection PyBroadException + try: + with PrintPatchLogger.recursion_protect_lock: + if hasattr(self._terminal, '_original_write'): + self._terminal._original_write(message) # noqa + else: + self._terminal.write(message) + except Exception: + pass do_flush = '\n' in message # check for CR character @@ -245,10 +249,14 @@ class PrintPatchLogger(object): # what can we do, nothing pass else: - if hasattr(self._terminal, '_original_write'): - self._terminal._original_write(message) # noqa - else: - self._terminal.write(message) + # noinspection PyBroadException + try: + if hasattr(self._terminal, '_original_write'): + self._terminal._original_write(message) # noqa + else: + self._terminal.write(message) + except Exception: + pass def connect(self, logger): # refresh if needed diff --git a/clearml/task.py b/clearml/task.py index 820ff182..d545eee5 100644 --- a/clearml/task.py +++ b/clearml/task.py @@ -3534,6 +3534,16 @@ class Task(_Task): # # we have to forcefully shutdown if we have forked processes, sometimes they will get stuck # os._exit(self.__exit_hook.exit_code if self.__exit_hook and self.__exit_hook.exit_code else 0) + @staticmethod + def _clear_loggers(): + # https://github.com/pytest-dev/pytest/issues/5502#issuecomment-647157873 + import logging + loggers = [logging.getLogger()] + list(logging.Logger.manager.loggerDict.values()) + for logger in loggers: + handlers = getattr(logger, 'handlers', []) + for handler in handlers: + logger.removeHandler(handler) + def __shutdown(self): """ Will happen automatically once we exit code, i.e. atexit @@ -3560,6 +3570,8 @@ class Task(_Task): # from here only a single thread can re-enter self._at_exit_called = get_current_thread_id() + Task._clear_loggers() + # disable lock on signal callbacks, to avoid deadlocks. if self.__exit_hook and self.__exit_hook.signal is not None: self.__edit_lock = False