Repository: mindspore-lab/mindocr (language: python)

Issue:
modify print to logger
Thank you for your contribution to the MindOCR repo.
Before submitting this PR, please make sure:

- [x] You have read the [Contributing Guidelines on pull requests](https://github.com/mindspore-lab/mindcv/blob/main/CONTRIBUTING.md)
- [x] Your code builds clean without any errors or warnings
- [x] You are using approved terminology
- [ ] You have added unit tests

## Motivation

(Write your motivation for proposed changes here.)

## Test Plan

(How should this PR be tested? Do you require special setup to run the test or repro the fixed bug?)

## Related Issues and PRs

(Is this PR part of a group of changes? Link the other relevant PRs and Issues here. Use https://help.github.com/en/articles/closing-issues-using-keywords for help on GitHub syntax)



Discussion / hints:

Fix patch:
diff --git a/mindocr/data/builder.py b/mindocr/data/builder.py
index 6ba9ce107..4aa5eab6c 100644
--- a/mindocr/data/builder.py
+++ b/mindocr/data/builder.py
@@ -1,16 +1,16 @@
+import logging
 import multiprocessing
 import os
 
 import mindspore as ms
 
-from ..utils.logger import Logger
 from .det_dataset import DetDataset, SynthTextDataset
 from .predict_dataset import PredictDataset
 from .rec_dataset import RecDataset
 from .rec_lmdb_dataset import LMDBDataset
 
 __all__ = ["build_dataset"]
-_logger = Logger("mindocr")
+_logger = logging.getLogger(__name__)
 
 supported_dataset_types = [
     "BaseDataset",
diff --git a/mindocr/data/det_dataset.py b/mindocr/data/det_dataset.py
index fcbf61cbc..6588f263d 100644
--- a/mindocr/data/det_dataset.py
+++ b/mindocr/data/det_dataset.py
@@ -1,3 +1,4 @@
+import logging
 import os
 import random
 from typing import List, Union
@@ -5,12 +6,11 @@
 import numpy as np
 from scipy.io import loadmat
 
-from ..utils.logger import Logger
 from .base_dataset import BaseDataset
 from .transforms.transforms_factory import create_transforms, run_transforms
 
 __all__ = ["DetDataset", "SynthTextDataset"]
-_logger = Logger("mindocr")
+_logger = logging.getLogger(__name__)
 
 
 class DetDataset(BaseDataset):
diff --git a/mindocr/data/rec_lmdb_dataset.py b/mindocr/data/rec_lmdb_dataset.py
index ce2401e19..29892533f 100644
--- a/mindocr/data/rec_lmdb_dataset.py
+++ b/mindocr/data/rec_lmdb_dataset.py
@@ -1,15 +1,15 @@
+import logging
 import os
 from typing import Any, List, Optional
 
 import lmdb
 import numpy as np
 
-from ..utils.logger import Logger
 from .base_dataset import BaseDataset
 from .transforms.transforms_factory import create_transforms, run_transforms
 
 __all__ = ["LMDBDataset"]
-_logger = Logger("mindocr")
+_logger = logging.getLogger(__name__)
 
 
 class LMDBDataset(BaseDataset):
diff --git a/mindocr/data/transforms/det_transforms.py b/mindocr/data/transforms/det_transforms.py
index 520a23b7e..500ccebe8 100644
--- a/mindocr/data/transforms/det_transforms.py
+++ b/mindocr/data/transforms/det_transforms.py
@@ -2,6 +2,7 @@
 transforms for text detection tasks.
 """
 import json
+import logging
 import math
 import random
 import warnings
@@ -12,8 +13,6 @@
 import pyclipper
 from shapely.geometry import Polygon, box
 
-from mindocr.utils.logger import Logger
-
 __all__ = [
     "DetLabelEncode",
     "BorderMap",
@@ -25,7 +24,7 @@
     "RandomCropWithMask",
     "DetResize",
 ]
-_logger = Logger("mindocr")
+_logger = logging.getLogger(__name__)
 
 
 class DetLabelEncode:
diff --git a/mindocr/data/transforms/rec_transforms.py b/mindocr/data/transforms/rec_transforms.py
index 3766a5691..875234bb6 100644
--- a/mindocr/data/transforms/rec_transforms.py
+++ b/mindocr/data/transforms/rec_transforms.py
@@ -1,14 +1,13 @@
 """
 transform for text recognition tasks.
 """
+import logging
 import math
 from typing import Any, Dict, List, Optional
 
 import cv2
 import numpy as np
 
-from mindocr.utils.logger import Logger
-
 __all__ = [
     "RecCTCLabelEncode",
     "RecAttnLabelEncode",
@@ -19,7 +18,7 @@
     "Rotate90IfVertical",
     "ClsLabelEncode",
 ]
-_logger = Logger("mindocr")
+_logger = logging.getLogger(__name__)
 
 
 class RecCTCLabelEncode(object):
@@ -263,7 +262,7 @@ def __init__(
             char_list = list("0123456789abcdefghijklmnopqrstuvwxyz")
 
             self.lower = True
-            print("INFO: The character_dict_path is None, model can only recognize number and lower letters")
+            _logger.info("The character_dict_path is None, model can only recognize number and lower letters")
         else:
             # parse char dictionary
             char_list = []
@@ -279,10 +278,9 @@ def __init__(
             self.space_idx = len(char_list) - 1
         else:
             if " " in char_list:
-                print(
-                    "WARNING: The dict still contains space char in dict although use_space_char is set to be False, "
-                    "because the space char is coded in the dictionary file ",
-                    character_dict_path,
+                _logger.warning(
+                    "The dict still contains space char in dict although use_space_char is set to be False, "
+                    f"because the space char is coded in the dictionary file {character_dict_path}"
                 )
 
         self.num_valid_chars = len(char_list)  # the number of valid chars (including space char if used)
diff --git a/mindocr/data/transforms/transforms_factory.py b/mindocr/data/transforms/transforms_factory.py
index f5c8cd9e0..c338fe263 100644
--- a/mindocr/data/transforms/transforms_factory.py
+++ b/mindocr/data/transforms/transforms_factory.py
@@ -1,12 +1,11 @@
 """
 Create and run transformations from a config or predefined transformation pipeline
 """
+import logging
 from typing import Dict, List
 
 import numpy as np
 
-from mindocr.utils.logger import Logger
-
 from .det_east_transforms import *
 from .det_fce_transforms import *
 from .det_transforms import *
@@ -15,7 +14,7 @@
 from .svtr_transform import *
 
 __all__ = ["create_transforms", "run_transforms", "transforms_dbnet_icdar15"]
-_logger = Logger("mindocr")
+_logger = logging.getLogger(__name__)
 
 
 # TODO: use class with __call__, to perform transformation
diff --git a/mindocr/losses/det_loss.py b/mindocr/losses/det_loss.py
index f986139b6..19744364c 100644
--- a/mindocr/losses/det_loss.py
+++ b/mindocr/losses/det_loss.py
@@ -1,3 +1,4 @@
+import logging
 from typing import Tuple, Union
 
 import numpy as np
@@ -7,10 +8,8 @@
 import mindspore.numpy as mnp
 from mindspore import Tensor, nn, ops
 
-from mindocr.utils.logger import Logger
-
 __all__ = ["L1BalancedCELoss", "PSEDiceLoss", "EASTLoss", "FCELoss"]
-_logger = Logger("mindocr")
+_logger = logging.getLogger(__name__)
 
 
 class L1BalancedCELoss(nn.LossBase):
diff --git a/mindocr/metrics/rec_metrics.py b/mindocr/metrics/rec_metrics.py
index 7998c6888..3bc829b88 100644
--- a/mindocr/metrics/rec_metrics.py
+++ b/mindocr/metrics/rec_metrics.py
@@ -1,4 +1,5 @@
 """Metric for accuracy evaluation."""
+import logging
 import re
 
 from rapidfuzz.distance import Levenshtein
@@ -8,6 +9,7 @@
 from mindspore import ms_function, nn
 
 __all__ = ["RecMetric"]
+_logger = logging.getLogger(__name__)
 
 
 class RecMetric(nn.Metric):
@@ -36,7 +38,7 @@ def __init__(
         ignore_symbol=False,
         print_flag=False,
         device_num=1,
-        **kwargs
+        **kwargs,
     ):
         super().__init__()
         self.clear()
@@ -91,7 +93,6 @@ def update(self, *inputs):
         preds, gt = inputs
         pred_texts = preds["texts"]
         # pred_confs = preds['confs']
-        # print('pred: ', pred_texts, len(pred_texts))
 
         # remove padded chars in GT
         if isinstance(gt, tuple) or isinstance(gt, list):
@@ -108,11 +109,7 @@ def update(self, *inputs):
             if isinstance(gt_texts, ms.Tensor):
                 gt_texts = gt_texts.asnumpy()
 
-        # print('2: ', gt_texts)
         for pred, label in zip(pred_texts, gt_texts):
-            # print('pred', pred, 'END')
-            # print('label ', label, 'END')
-
             if self.ignore_space:
                 pred = pred.replace(" ", "")
                 label = label.replace(" ", "")
@@ -130,7 +127,7 @@ def update(self, *inputs):
                 pred = self.valid_symbol.sub("", pred)
 
             if self.print_flag:
-                print(pred, " :: ", label)
+                _logger.info(f"{pred} :: {label}")
 
             edit_distance = Levenshtein.normalized_distance(pred, label)
             self._norm_edit_dis += edit_distance
@@ -147,7 +144,7 @@ def all_reduce_fun(self, x):
     def eval(self):
         if self._total_num == 0:
             raise RuntimeError("Accuary can not be calculated, because the number of samples is 0.")
-        print("correct num: ", self._correct_num, ", total num: ", self._total_num)
+        _logger.info(f"correct num: {self._correct_num}, total num: {self._total_num}")
 
         if self.all_reduce:
             # sum over all devices
diff --git a/mindocr/models/backbones/mindcv_models/utils.py b/mindocr/models/backbones/mindcv_models/utils.py
index 46402894c..0ee4b0c14 100644
--- a/mindocr/models/backbones/mindcv_models/utils.py
+++ b/mindocr/models/backbones/mindcv_models/utils.py
@@ -3,6 +3,7 @@
 """
 import collections.abc
 import difflib
+import logging
 import os
 from copy import deepcopy
 from itertools import repeat
@@ -10,11 +11,9 @@
 
 from mindspore import load_checkpoint, load_param_into_net
 
-from mindocr.utils.logger import Logger
-
 from .download import DownLoad, get_default_download_root
 
-_logger = Logger("mindocr")
+_logger = logging.getLogger(__name__)
 
 
 def get_checkpoint_download_root():
diff --git a/mindocr/models/backbones/mindcv_wrapper.py b/mindocr/models/backbones/mindcv_wrapper.py
index bf3e8d4af..360864cbd 100644
--- a/mindocr/models/backbones/mindcv_wrapper.py
+++ b/mindocr/models/backbones/mindcv_wrapper.py
@@ -1,3 +1,4 @@
+import logging
 from typing import List
 
 import numpy as np
@@ -5,11 +6,9 @@
 import mindspore as ms
 from mindspore import load_checkpoint, load_param_into_net, nn, ops
 
-from mindocr.utils.logger import Logger
-
 from . import mindcv_models
 
-_logger = Logger("mindocr")
+_logger = logging.getLogger(__name__)
 
 
 class MindCVBackboneWrapper(nn.Cell):
diff --git a/mindocr/models/utils/load_model.py b/mindocr/models/utils/load_model.py
index 504dbae7d..ec0f3f652 100644
--- a/mindocr/models/utils/load_model.py
+++ b/mindocr/models/utils/load_model.py
@@ -1,14 +1,13 @@
+import logging
 import os
 from typing import Callable, Dict, Optional
 
 from mindspore import load_checkpoint, load_param_into_net
 
-from mindocr.utils.logger import Logger
-
 from ..backbones.mindcv_models.utils import auto_map, download_pretrained
 
 __all__ = ["load_model", "drop_inconsistent_shape_parameters"]
-_logger = Logger("mindocr")
+_logger = logging.getLogger(__name__)
 
 
 def drop_inconsistent_shape_parameters(model, param_dict):
diff --git a/mindocr/optim/optim_factory.py b/mindocr/optim/optim_factory.py
index caa2f4d30..3f5901b4b 100644
--- a/mindocr/optim/optim_factory.py
+++ b/mindocr/optim/optim_factory.py
@@ -1,18 +1,18 @@
 """ optim factory """
 import inspect
+import logging
 import os
 from typing import Optional
 
 from mindspore import load_checkpoint, load_param_into_net, nn
 
-from ..utils.logger import Logger
 from .adamw import AdamW
 from .adan import Adan
 from .lion import Lion
 from .nadam import NAdam
 
 __all__ = ["create_optimizer"]
-_logger = Logger("mindocr")
+_logger = logging.getLogger(__name__)
 
 
 def init_group_params(params, weight_decay):
diff --git a/mindocr/optim/param_grouping.py b/mindocr/optim/param_grouping.py
index dd1c1eb3f..62ce5ae5c 100644
--- a/mindocr/optim/param_grouping.py
+++ b/mindocr/optim/param_grouping.py
@@ -1,12 +1,12 @@
 """
 group parameters for setting different weight decay or learning rate for different layers in the network.
 """
-from ..utils.logger import Logger
+import logging
 
 __all__ = ["create_group_params"]
 
 supported_grouping_strategies = ["svtr", "filter_norm_and_bias"]
-_logger = Logger("mindocr")
+_logger = logging.getLogger(__name__)
 
 
 def grouping_default(params, weight_decay):
diff --git a/mindocr/postprocess/det_base_postprocess.py b/mindocr/postprocess/det_base_postprocess.py
index ce013cb20..c00f944f6 100644
--- a/mindocr/postprocess/det_base_postprocess.py
+++ b/mindocr/postprocess/det_base_postprocess.py
@@ -1,3 +1,4 @@
+import logging
 from typing import Dict, List, Tuple, Union
 
 import numpy as np
@@ -5,10 +6,8 @@
 import mindspore as ms
 from mindspore import Tensor
 
-from ..utils.logger import Logger
-
 __all__ = ["DetBasePostprocess"]
-_logger = Logger("mindocr")
+_logger = logging.getLogger(__name__)
 
 
 class DetBasePostprocess:
diff --git a/mindocr/postprocess/rec_postprocess.py b/mindocr/postprocess/rec_postprocess.py
index d7526c8f5..1b79b8921 100644
--- a/mindocr/postprocess/rec_postprocess.py
+++ b/mindocr/postprocess/rec_postprocess.py
@@ -1,15 +1,14 @@
 """
 """
+import logging
 from typing import Any, Dict, List, Optional, Tuple, Union
 
 import numpy as np
 
 from mindspore import Tensor
 
-from ..utils.logger import Logger
-
 __all__ = ["RecCTCLabelDecode", "RecAttnLabelDecode", "RecMasterLabelDecode"]
-_logger = Logger("mindocr")
+_logger = logging.getLogger(__name__)
 
 
 class RecCTCLabelDecode(object):
@@ -312,7 +311,7 @@ def __init__(
             char_list = list("0123456789abcdefghijklmnopqrstuvwxyz")
 
             self.lower = True
-            print("INFO: The character_dict_path is None, model can only recognize number and lower letters")
+            _logger.info("The character_dict_path is None, model can only recognize number and lower letters")
         else:
             # parse char dictionary
             char_list = []
@@ -328,10 +327,9 @@ def __init__(
             self.space_idx = len(char_list) - 1
         else:
             if " " in char_list:
-                print(
-                    "WARNING: The dict still contains space char in dict although use_space_char is set to be False, "
-                    "because the space char is coded in the dictionary file ",
-                    character_dict_path,
+                _logger.warning(
+                    "The dict still contains space char in dict although use_space_char is set to be False, "
+                    f"because the space char is coded in the dictionary file {character_dict_path}"
                 )
 
         self.num_valid_chars = len(char_list)  # the number of valid chars (including space char if used)
diff --git a/mindocr/scheduler/scheduler_factory.py b/mindocr/scheduler/scheduler_factory.py
index 2bf923f72..4dfacfe38 100644
--- a/mindocr/scheduler/scheduler_factory.py
+++ b/mindocr/scheduler/scheduler_factory.py
@@ -1,5 +1,6 @@
 """Scheduler Factory"""
-from ..utils.logger import Logger
+import logging
+
 from .dynamic_lr import (
     cosine_decay_lr,
     cosine_decay_refined_lr,
@@ -14,7 +15,7 @@
 )
 
 __all__ = ["create_scheduler"]
-_logger = Logger("mindocr")
+_logger = logging.getLogger(__name__)
 
 
 def create_scheduler(
diff --git a/mindocr/utils/callbacks.py b/mindocr/utils/callbacks.py
index 2325cfc95..f4e12efaa 100644
--- a/mindocr/utils/callbacks.py
+++ b/mindocr/utils/callbacks.py
@@ -1,3 +1,4 @@
+import logging
 import os
 import time
 from typing import List, Tuple
@@ -8,11 +9,11 @@
 
 from .checkpoint import CheckpointManager
 from .evaluator import Evaluator
-from .logger import Logger
 from .misc import AllReduce, AverageMeter, fetch_optimizer_lr
 from .recorder import PerfRecorder
 
 __all__ = ["EvalSaveCallback"]
+_logger = logging.getLogger(__name__)
 
 
 class EvalSaveCallback(Callback):
@@ -35,7 +36,6 @@ def __init__(
         pred_cast_fp32=False,
         rank_id=0,
         device_num=None,
-        logger=None,
         batch_size=20,
         ckpt_save_dir="./",
         main_indicator="hmean",
@@ -56,12 +56,6 @@ def __init__(
         self.loader_eval = loader
         self.network = network
         self.ema = ema
-
-        if logger is None:
-            self.logger = Logger("mindocr", rank=self.rank_id)
-        else:
-            self.logger = logger
-
         self.val_interval = val_interval
         self.val_start_epoch = val_start_epoch
         self.log_interval = log_interval
@@ -149,7 +143,7 @@ def on_train_step_end(self, run_context):
                 f"loss: {loss:.6f}, " + lr_str + f"per step time: {per_step_time:.3f} ms, fps: {fps:.2f} img/s"
             )
 
-            self.logger.info(msg)
+            _logger.info(msg)
             self.step_start_time = time.time()
 
     def on_train_epoch_begin(self, run_context):
@@ -187,7 +181,7 @@ def on_train_epoch_end(self, run_context):
             f"epoch: [{cur_epoch}/{cb_params.epoch_num+self.start_epoch}], loss: {train_loss:.6f}, "
             f"epoch time: {epoch_time:.3f} s, per step time: {per_step_time:.3f} ms, fps: {fps:.2f} img/s"
         )
-        self.logger.info(msg)
+        _logger.info(msg)
 
         eval_done = False
         if self.loader_eval is not None:
@@ -202,7 +196,7 @@ def on_train_epoch_end(self, run_context):
                 if self.is_main_device:
                     perf = measures[self.main_indicator]
                     eval_time = time.time() - eval_start
-                    self.logger.info(f"Performance: {measures}, eval time: {eval_time}")
+                    _logger.info(f"Performance: {measures}, eval time: {eval_time}")
             else:
                 measures = {m_name: None for m_name in self.net_evaluator.metric_names}
                 eval_time = 0
@@ -220,7 +214,7 @@ def on_train_epoch_end(self, run_context):
                 # ema weight will be saved if enabled.
                 save_checkpoint(self.network, os.path.join(self.ckpt_save_dir, "best.ckpt"))
 
-                self.logger.info(f"=> Best {self.main_indicator}: {self.best_perf}, checkpoint saved.")
+                _logger.info(f"=> Best {self.main_indicator}: {self.best_perf}, checkpoint saved.")
 
             # save history checkpoints
             self.ckpt_manager.save(self.network, perf, ckpt_name=f"e{cur_epoch}.ckpt")
@@ -255,10 +249,10 @@ def on_train_epoch_end(self, run_context):
     def on_train_end(self, run_context):
         if self.is_main_device:
             self.rec.save_curves()  # save performance curve figure
-            self.logger.info(f"=> Best {self.main_indicator}: {self.best_perf} \nTraining completed!")
+            _logger.info(f"=> Best {self.main_indicator}: {self.best_perf} \nTraining completed!")
 
             if self.ckpt_save_policy == "top_k":
                 log_str = f"Top K checkpoints:\n{self.main_indicator}\tcheckpoint\n"
                 for p, ckpt_name in self.ckpt_manager.get_ckpt_queue():
                     log_str += f"{p:.4f}\t{os.path.join(self.ckpt_save_dir, ckpt_name)}\n"
-                self.logger.info(log_str)
+                _logger.info(log_str)
diff --git a/mindocr/utils/checkpoint.py b/mindocr/utils/checkpoint.py
index 8912a9e3a..b17c1b58f 100644
--- a/mindocr/utils/checkpoint.py
+++ b/mindocr/utils/checkpoint.py
@@ -1,12 +1,11 @@
 """checkpoint manager """
+import logging
 import os
 import stat
 
 import mindspore as ms
 
-from .logger import Logger
-
-_logger = Logger("mindocr")
+_logger = logging.getLogger(__name__)
 
 
 class CheckpointManager:
diff --git a/mindocr/utils/evaluator.py b/mindocr/utils/evaluator.py
index 0a4cc08b8..75b1227b7 100644
--- a/mindocr/utils/evaluator.py
+++ b/mindocr/utils/evaluator.py
@@ -1,3 +1,4 @@
+import logging
 from typing import List
 
 from tqdm import tqdm
@@ -6,10 +7,8 @@
 from mindspore.common import dtype as mstype
 from mindspore.ops import functional as F
 
-from .logger import Logger
-
 __all__ = ["Evaluator"]
-_logger = Logger("mindocr")
+_logger = logging.getLogger(__name__)
 
 
 class Evaluator:
diff --git a/mindocr/utils/logger.py b/mindocr/utils/logger.py
index cf5cdd202..d9866cbee 100644
--- a/mindocr/utils/logger.py
+++ b/mindocr/utils/logger.py
@@ -1,80 +1,71 @@
-"""Custom Logger."""
+"""Set Logger
+
+The implementation is based on https://github.com/serend1p1ty/core-pytorch-utils/blob/main/cpu/logger.py
+"""
 import logging
 import os
 import sys
+from typing import Optional
 
+__all__ = [
+    "set_logger",
+]
 
-class Logger(logging.Logger):
-    """
-    Logger.
-
-    Args:
-         logger_name: String. Logger name.
-         rank: Integer. Rank id.
-    """
-
-    def __init__(self, logger_name, rank=0, log_fn=None):
-        super(Logger, self).__init__(logger_name)
-        self.rank = rank or 0
-        self.log_fn = log_fn
-        is_main_device = not rank
+logger_initialized = {}
 
-        if is_main_device:
-            console = logging.StreamHandler(sys.stdout)
-            console.setLevel(logging.INFO)
-            formatter = logging.Formatter("%(asctime)s:%(levelname)s:%(message)s")
-            console.setFormatter(formatter)
-            self.addHandler(console)
 
-    def setup_logging_file(self, log_dir):
-        """Setup logging file."""
-        if not os.path.exists(log_dir):
-            os.makedirs(log_dir, exist_ok=True)
-        if self.log_fn is None:
-            log_name = "log_%s.txt" % self.rank
-            self.log_save_path = os.path.join(log_dir, log_name)
-        else:
-            self.log_save_path = os.path.join(log_dir, self.log_fn)
-        fh = logging.FileHandler(self.log_save_path)
-        fh.setLevel(logging.INFO)
-        formatter = logging.Formatter("%(asctime)s:%(levelname)s:%(message)s")
-        fh.setFormatter(formatter)
-        self.addHandler(fh)
+def set_logger(
+    name: Optional[str] = None,
+    output_dir: Optional[str] = None,
+    log_fn: Optional[str] = None,
+    rank: int = 0,
+    log_level: Optional[str] = logging.INFO,
+) -> logging.Logger:
+    """Initialize the logger.
 
-    def info(self, msg, *args, **kwargs):
-        if self.isEnabledFor(logging.INFO):
-            self._log(logging.INFO, msg, args, **kwargs)
+    If the logger has not been initialized, this method will initialize the
+    logger by adding one or two handlers, otherwise the initialized logger will
+    be directly returned. During initialization, only logger of the master
+    process is added console handler. If ``output_dir`` is specified, all loggers
+    will be added file handler.
 
-    def warning(self, msg, *args, **kwargs):
-        if self.isEnabledFor(logging.WARNING):
-            self._log(logging.WARNING, msg, args, **kwargs)
+    Args:
+        name: Logger name. Defaults to None to set up root logger.
+        output_dir: The directory to save log.
+        log_fn: The name to save log.
+        rank: Process rank in the distributed training. Defaults to 0.
+        log_level: Verbosity level of the logger. Defaults to ``logging.INFO``.
 
-    def error(self, msg, *args, **kwargs):
-        if self.isEnabledFor(logging.ERROR):
-            self._log(logging.ERROR, msg, args, **kwargs)
+    Returns:
+        logging.Logger: A initialized logger.
+    """
+    if name in logger_initialized:
+        return logger_initialized[name]
 
-    def save_args(self, args):
-        self.info("Args:")
-        args_dict = vars(args)
-        for key in args_dict.keys():
-            self.info("--> %s: %s", key, args_dict[key])
-        self.info("")
+    # get root logger if name is None
+    logger = logging.getLogger(name)
+    logger.setLevel(log_level)
+    # the messages of this logger will not be propagated to its parent
+    logger.propagate = False
 
-    def important_info(self, msg, *args, **kwargs):
-        if self.isEnabledFor(logging.INFO) and self.rank == 0:
-            line_width = 2
-            important_msg = "\n"
-            important_msg += ("*" * 70 + "\n") * line_width
-            important_msg += ("*" * line_width + "\n") * 2
-            important_msg += "*" * line_width + " " * 8 + msg + "\n"
-            important_msg += ("*" * line_width + "\n") * 2
-            important_msg += ("*" * 70 + "\n") * line_width
-            self.info(important_msg, *args, **kwargs)
+    fmt = "%(asctime)s %(name)s %(levelname)s - %(message)s"
+    datefmt = "[%Y-%m-%d %H:%M:%S]"
 
+    # create console handler for master process
+    if rank == 0:
+        console_handler = logging.StreamHandler(stream=sys.stdout)
+        console_handler.setLevel(log_level)
+        console_handler.setFormatter(logging.Formatter(fmt=fmt, datefmt=datefmt))
+        logger.addHandler(console_handler)
 
-def get_logger(log_dir, rank, log_fn=None):
-    """Get Logger."""
-    logger = Logger("mindocr", rank, log_fn=log_fn)
-    logger.setup_logging_file(log_dir)
+    if output_dir is not None:
+        os.makedirs(output_dir, exist_ok=True)
+        if log_fn is None:
+            log_fn = "log_%s.txt" % rank
+        file_handler = logging.FileHandler(os.path.join(output_dir, log_fn))
+        file_handler.setLevel(log_level)
+        file_handler.setFormatter(logging.Formatter(fmt=fmt, datefmt=datefmt))
+        logger.addHandler(file_handler)
 
+    logger_initialized[name] = logger
     return logger
diff --git a/mindocr/utils/loss_scaler.py b/mindocr/utils/loss_scaler.py
index fe473ee26..f0f90e2bf 100644
--- a/mindocr/utils/loss_scaler.py
+++ b/mindocr/utils/loss_scaler.py
@@ -1,5 +1,9 @@
+import logging
+
 from mindspore import nn
 
+_logger = logging.getLogger(__name__)
+
 
 def get_loss_scales(cfg):
     """
@@ -34,8 +38,8 @@ def get_loss_scales(cfg):
             if grad_accu_steps > 1:
                 scale_factor = scale_factor ** (1 / grad_accu_steps)
                 scale_window = scale_window * grad_accu_steps
-                print(
-                    "INFO: gradient_accumulation_steps > 1, scale_factor and scale_window are adjusted accordingly for "
+                _logger.info(
+                    "gradient_accumulation_steps > 1, scale_factor and scale_window are adjusted accordingly for "
                     "dynamic loss scaler"
                 )
             loss_scale_manager = nn.DynamicLossScaleUpdateCell(
diff --git a/mindocr/utils/recorder.py b/mindocr/utils/recorder.py
index 653d602b4..9e6e74822 100644
--- a/mindocr/utils/recorder.py
+++ b/mindocr/utils/recorder.py
@@ -1,3 +1,4 @@
+import logging
 import os
 from typing import List
 
@@ -6,9 +7,7 @@
 
 import mindspore as ms
 
-from .logger import Logger
-
-_logger = Logger("mindocr")
+_logger = logging.getLogger(__name__)
 
 
 def plot_result(result_path, save_fig=False, sep="\t", na_padding="last", replace_val=-1):
diff --git a/mindocr/utils/visualize.py b/mindocr/utils/visualize.py
index 94ce77e3e..5ba26bc0a 100644
--- a/mindocr/utils/visualize.py
+++ b/mindocr/utils/visualize.py
@@ -1,3 +1,4 @@
+import logging
 import math
 from typing import List, Union
 
@@ -7,10 +8,9 @@
 from PIL import Image, ImageDraw, ImageFont
 
 from ..data.constants import IMAGENET_DEFAULT_MEAN, IMAGENET_DEFAULT_STD
-from .logger import Logger
 
 __all__ = ["show_img", "show_imgs", "draw_boxes", "draw_texts_with_boxes", "recover_image", "visualize"]
-_logger = Logger("mindocr")
+_logger = logging.getLogger(__name__)
 
 
 def show_img(img: np.array, is_bgr_img=True, title="img", show=True, save_path=None):
diff --git a/tools/benchmarking/multi_dataset_eval.py b/tools/benchmarking/multi_dataset_eval.py
index 0dea174d8..d18ce02ca 100644
--- a/tools/benchmarking/multi_dataset_eval.py
+++ b/tools/benchmarking/multi_dataset_eval.py
@@ -40,6 +40,7 @@
 """
 
 import copy
+import logging
 import os
 import sys
 
@@ -59,14 +60,15 @@
 from mindocr.models import build_model
 from mindocr.postprocess import build_postprocess
 from mindocr.utils.callbacks import Evaluator
-from mindocr.utils.logger import Logger
+from mindocr.utils.logger import set_logger
 
-_logger = Logger("mindocr")
+logger = logging.getLogger("mindocr")
 
 
 def main(cfg):
     # env init
     ms.set_context(mode=cfg.system.mode)
+    set_logger(name="mindocr")
     if cfg.system.distribute:
         init()
         device_num = get_group_size()
@@ -101,7 +103,7 @@ def main(cfg):
     network.set_train(False)
 
     if not cfg.system.amp_level_infer and cfg.system.amp_level != "O0":
-        _logger.info("Evaluation will run in full-precision(fp32)")
+        logger.info("Evaluation will run in full-precision(fp32)")
 
     # postprocess, metric
     postprocessor = build_postprocess(cfg.postprocess)
@@ -157,17 +159,17 @@ def main(cfg):
                 )
 
             # log
-            _logger.info("=" * 40)
-            _logger.info(f"Num batches: {num_batches}")
+            logger.info("=" * 40)
+            logger.info(f"Num batches: {num_batches}")
             if "name" in cfg.model:
-                _logger.info(f"Model: {cfg.model.name}")
+                logger.info(f"Model: {cfg.model.name}")
             else:
-                _logger.info(f"Model: {cfg.model.backbone.name}-{cfg.model.neck.name}-{cfg.model.head.name}")
-            _logger.info("=" * 40)
+                logger.info(f"Model: {cfg.model.backbone.name}-{cfg.model.neck.name}-{cfg.model.head.name}")
+            logger.info("=" * 40)
 
             measures = net_evaluator.eval()
             if is_main_device:
-                _logger.info(f"Performance: {measures}")
+                logger.info(f"Performance: {measures}")
 
             results.append(measures)
             acc_summary[dirpath] = measures
@@ -185,9 +187,9 @@ def main(cfg):
 
     acc_summary["Average"] = avg_dict
 
-    _logger.info(f"Average score: {avg_dict}")
+    logger.info(f"Average score: {avg_dict}")
 
-    _logger.info(f"Summary: {acc_summary}")
+    logger.info(f"Summary: {acc_summary}")
 
 
 def parse_args():
diff --git a/tools/eval.py b/tools/eval.py
index 96d5f40b3..e61bb00c0 100644
--- a/tools/eval.py
+++ b/tools/eval.py
@@ -1,6 +1,7 @@
 """
 Model evaluation
 """
+import logging
 import os
 import sys
 
@@ -17,9 +18,11 @@
 from mindocr.models import build_model
 from mindocr.postprocess import build_postprocess
 from mindocr.utils.evaluator import Evaluator
-from mindocr.utils.logger import get_logger
+from mindocr.utils.logger import set_logger
 from tools.arg_parser import parse_args_and_config
 
+logger = logging.getLogger("mindocr.eval")
+
 
 def main(cfg):
     # env init
@@ -33,30 +36,26 @@ def main(cfg):
             parallel_mode="data_parallel",
             gradients_mean=True,
         )
+        set_logger(
+            name="mindocr", output_dir=cfg.train.ckpt_save_dir or "./", log_fn=f"log_eval_{rank_id}.txt", rank=rank_id
+        )
     else:
         device_num = None
         rank_id = None
+        set_logger(name="mindocr", output_dir=cfg.train.ckpt_save_dir or "./", log_fn=f"log_eval_{rank_id}.txt", rank=0)
         if "DEVICE_ID" in os.environ:
-            print(
-                f"INFO: Standalone evaluation. Device id: {os.environ.get('DEVICE_ID')}, "
+            logger.info(
+                f"Standalone evaluation. Device id: {os.environ.get('DEVICE_ID')}, "
                 f"specified by environment variable 'DEVICE_ID'."
             )
         else:
             device_id = cfg.system.get("device_id", 0)
             ms.set_context(device_id=device_id)
-            print(
-                f"INFO: Standalone evaluation. Device id: {device_id}, "
+            logger.info(
+                f"Standalone evaluation. Device id: {device_id}, "
                 f"specified by system.device_id in yaml config file or is default value 0."
             )
 
-    is_main_device = rank_id in [None, 0]
-
-    logger = get_logger(
-        log_dir=cfg.train.ckpt_save_dir or "./",
-        rank=rank_id,
-        log_fn=f"log_eval_{rank_id}.txt",
-    )
-
     # load dataset
     loader_eval = build_dataset(
         cfg.eval.dataset,
@@ -130,7 +129,7 @@ def main(cfg):
     )
 
     measures = net_evaluator.eval()
-    if is_main_device:
+    if rank_id in [None, 0]:
         logger.info(f"Performance: {measures}")
 
 
diff --git a/tools/export.py b/tools/export.py
index 94d208682..84277c18c 100644
--- a/tools/export.py
+++ b/tools/export.py
@@ -23,8 +23,8 @@
         performance.
     - The online ckpt files are downloaded from https://download.mindspore.cn/toolkits/mindocr/.
 """
-
 import argparse
+import logging
 import os
 import sys
 
@@ -37,13 +37,14 @@
 sys.path.insert(0, os.path.abspath(os.path.join(__dir__, "..")))
 
 from mindocr import build_model, list_models
-from mindocr.utils.logger import Logger
+from mindocr.utils.logger import set_logger
 
-_logger = Logger("mindocr")
+logger = logging.getLogger("mindocr.export")
 
 
 def export(name_or_config, data_shape, local_ckpt_path, save_dir):
     ms.set_context(mode=ms.GRAPH_MODE)  # , device_target="Ascend")
+    set_logger(name="mindocr")
 
     if name_or_config.endswith(".yml") or name_or_config.endswith(".yaml"):
         with open(name_or_config, "r") as f:
@@ -65,7 +66,7 @@ def export(name_or_config, data_shape, local_ckpt_path, save_dir):
     else:
         net = build_model(model_cfg, pretrained=True, amp_level=amp_level)
 
-    _logger.info(f"Set the AMP level of the model to be `{amp_level}`.")
+    logger.info(f"Set the AMP level of the model to be `{amp_level}`.")
 
     net.set_train(False)
 
@@ -76,9 +77,7 @@ def export(name_or_config, data_shape, local_ckpt_path, save_dir):
     output_path = os.path.join(save_dir, name) + ".mindir"
     ms.export(net, x, file_name=output_path, file_format="MINDIR")
 
-    _logger.info(
-        f"=> Finish exporting {name} to {os.path.realpath(output_path)}. The data shape [H, W] is {data_shape}"
-    )
+    logger.info(f"=> Finish exporting {name} to {os.path.realpath(output_path)}. The data shape [H, W] is {data_shape}")
 
 
 def check_args(args):
diff --git a/tools/infer/text/parallel/README.md b/tools/infer/text/parallel/README.md
index 484e3c8b5..5e4174a7a 100644
--- a/tools/infer/text/parallel/README.md
+++ b/tools/infer/text/parallel/README.md
@@ -76,7 +76,7 @@ Otherwise, the args values in (1) yaml config file will be used by default. You
    Run the following command to start the detection and recognition prediction pipeline. **Note that the args values below will overwrite their counterparts in yaml config file.**
 
    ```bash
-   python tools/predict/text/parallel/predict_system.py \
+   python tools/infer/text/parallel/predict_system.py \
                 --raw_data_dir path/to/raw_data \
                 --det_ckpt_path path/to/detection_ckpt \
                 --rec_ckpt_path path/to/recognition_ckpt
diff --git a/tools/infer/text/parallel/README_CN.md b/tools/infer/text/parallel/README_CN.md
index 6198508ee..4c88ee881 100644
--- a/tools/infer/text/parallel/README_CN.md
+++ b/tools/infer/text/parallel/README_CN.md
@@ -74,7 +74,7 @@
    运行以下命令，开始串联推理。**以下传入的参数值将覆盖yaml文件中的对应参数值。**
 
    ```bash
-   python tools/predict/text/parallel/predict_system.py \
+   python tools/infer/text/parallel/predict_system.py \
                 --raw_data_dir path/to/raw_data \
                 --det_ckpt_path path/to/detection_ckpt \
                 --rec_ckpt_path path/to/recognition_ckpt
diff --git a/tools/infer/text/parallel/base_predict.py b/tools/infer/text/parallel/base_predict.py
index 011f52407..6fd795199 100644
--- a/tools/infer/text/parallel/base_predict.py
+++ b/tools/infer/text/parallel/base_predict.py
@@ -1,3 +1,4 @@
+import logging
 import os
 import sys
 
@@ -15,17 +16,18 @@
 from mindocr.data import build_dataset
 from mindocr.models import build_model
 from mindocr.postprocess import build_postprocess
-from mindocr.utils.logger import Logger
+from mindocr.utils.logger import set_logger
 
-_logger = Logger("mindocr")
+logger = logging.getLogger("mindocr")
 
 
 class BasePredict(object):
     def __init__(self, predict_cfg):
         # env init
         ms.set_context(mode=predict_cfg.system.mode)
+        set_logger(name="mindocr")
         if predict_cfg.system.distribute:
-            _logger.warning("Distribut mode blocked. Evaluation only runs in standalone mode.")
+            logger.warning("Distribut mode blocked. Evaluation only runs in standalone mode.")
 
         self.loader_predict = build_dataset(
             predict_cfg.predict.dataset, predict_cfg.predict.loader, num_shards=None, shard_id=None, is_train=False
@@ -44,7 +46,7 @@ def __init__(self, predict_cfg):
         self.network.set_train(False)
 
         if predict_cfg.system.amp_level != "O0":
-            _logger.info("Evaluation will run in full-precision(fp32)")
+            logger.info("Evaluation will run in full-precision(fp32)")
 
         # TODO: check float type conversion in official Model.eval
         # ms.amp.auto_mixed_precision(network, amp_level='O0')
diff --git a/tools/infer/text/parallel/predict_system.py b/tools/infer/text/parallel/predict_system.py
index 45479cd9a..b22326c39 100644
--- a/tools/infer/text/parallel/predict_system.py
+++ b/tools/infer/text/parallel/predict_system.py
@@ -1,4 +1,5 @@
 import argparse
+import logging
 import os
 import sys
 
@@ -12,8 +13,11 @@
 import cv2
 import numpy as np
 
+from mindocr.utils.logger import set_logger
 from mindocr.utils.visualize import recover_image
 
+logger = logging.getLogger("mindocr")
+
 
 def parse_args():
     """
@@ -142,12 +146,13 @@ def predict_rec(args, det_pred_outputs):
 
 def main():
     args = parse_args()
+    set_logger(name="mindocr")
     det_pred_outputs = predict_det(args)
-    print("Detection finished!")
+    logger.info("Detection finished!")
     det_pred_outputs = rescale(det_pred_outputs)
-    print("Rescale finished!")
+    logger.info("Rescale finished!")
     predict_rec(args, det_pred_outputs)
-    print("Detection and recognition finished!!!")
+    logger.info("Detection and recognition finished!!!")
 
 
 if __name__ == "__main__":
diff --git a/tools/infer/text/parallel/utils_predict.py b/tools/infer/text/parallel/utils_predict.py
index 096c4423d..109a0712c 100644
--- a/tools/infer/text/parallel/utils_predict.py
+++ b/tools/infer/text/parallel/utils_predict.py
@@ -1,4 +1,5 @@
 import json
+import logging
 import os
 import shutil
 
@@ -6,9 +7,7 @@
 import yaml
 from addict import Dict
 
-from mindocr.utils.logger import Logger
-
-_logger = Logger("mindocr")
+_logger = logging.getLogger("mindocr")
 
 
 def check_args(args):
diff --git a/tools/infer/text/predict_det.py b/tools/infer/text/predict_det.py
index f8c6cdd62..772132141 100644
--- a/tools/infer/text/predict_det.py
+++ b/tools/infer/text/predict_det.py
@@ -6,6 +6,7 @@
 """
 
 import json
+import logging
 import os
 import sys
 from typing import List
@@ -24,7 +25,7 @@
 
 from mindocr import build_model
 from mindocr.data.constants import IMAGENET_DEFAULT_MEAN, IMAGENET_DEFAULT_STD
-from mindocr.utils.logger import Logger
+from mindocr.utils.logger import set_logger
 from mindocr.utils.visualize import draw_boxes, show_imgs
 
 # map algorithm name to model name (which can be checked by `mindocr.list_models()`)
@@ -35,7 +36,7 @@
     "DB_MV3": "dbnet_mobilenetv3",
     "PSE": "psenet_resnet152",
 }
-_logger = Logger("mindocr")
+logger = logging.getLogger("mindocr")
 
 
 class TextDetector(object):
@@ -57,7 +58,7 @@ def __init__(self, args):
             model_name, pretrained=pretrained, ckpt_load_path=ckpt_load_path, amp_level=args.det_amp_level
         )
         self.model.set_train(False)
-        _logger.info(
+        logger.info(
             "Init detection model: {} --> {}. Model weights loaded from {}".format(
                 args.det_algorithm, model_name, "pretrained url" if pretrained else ckpt_load_path
             )
@@ -110,8 +111,8 @@ def __call__(self, img_or_path, do_visualize=True):
                 show=False,
                 save_path=os.path.join(self.vis_dir, fn + "_det_preproc.png"),
             )
-        _logger.info(f"Original image shape: {data['image_ori'].shape}")
-        _logger.info(f"After det preprocess: {data['image'].shape}")
+        logger.info(f"Original image shape: {data['image_ori'].shape}")
+        logger.info(f"After det preprocess: {data['image'].shape}")
 
         # infer
         input_np = data["image"]
@@ -174,7 +175,7 @@ def validate_det_res(det_res, img_shape, order_clockwise=True, min_poly_points=3
             if len(poly) == 4:
                 poly = order_points_clockwise(poly)
             else:
-                _logger.warning("order_clockwise only supports quadril polygons currently")
+                logger.warning("order_clockwise only supports quadril polygons currently")
         # filter
         if len(poly) < min_poly_points:
             continue
@@ -228,6 +229,7 @@ def save_det_res(det_res_all: List[dict], img_paths: List[str], include_score=Fa
 if __name__ == "__main__":
     # parse args
     args = parse_args()
+    set_logger(name="mindocr")
     save_dir = args.draw_img_save_dir
     img_paths = get_image_paths(args.image_dir)
     # uncomment it to quick test the infer FPS
@@ -241,12 +243,12 @@ def save_det_res(det_res_all: List[dict], img_paths: List[str], include_score=Fa
     # run for each image
     det_res_all = []
     for i, img_path in enumerate(img_paths):
-        print(f"\nINFO: Infering [{i+1}/{len(img_paths)}]: ", img_path)
+        logger.info(f"\nInfering [{i+1}/{len(img_paths)}]: {img_path}")
         det_res, _ = text_detect(img_path, do_visualize=True)
         det_res_all.append(det_res)
-        print(f"INFO: Num detected text boxes: {len(det_res['polys'])}")
+        logger.info(f"Num detected text boxes: {len(det_res['polys'])}")
 
     # save all results in a txt file
     save_det_res(det_res_all, img_paths, save_path=os.path.join(save_dir, "det_results.txt"))
 
-    print("Done! Text detection results saved in ", save_dir)
+    logger.info(f"Done! Text detection results saved in {save_dir}")
diff --git a/tools/infer/text/predict_rec.py b/tools/infer/text/predict_rec.py
index e7251ef40..24a869507 100644
--- a/tools/infer/text/predict_rec.py
+++ b/tools/infer/text/predict_rec.py
@@ -5,6 +5,7 @@
     $ python tools/infer/text/predict_rec.py  --image_dir {path_to_img} --rec_algorithm CRNN
     $ python tools/infer/text/predict_rec.py  --image_dir {path_to_img} --rec_algorithm CRNN_CH
 """
+import logging
 import os
 import sys
 from time import time
@@ -23,7 +24,7 @@
 sys.path.insert(0, os.path.abspath(os.path.join(__dir__, "../../../")))
 
 from mindocr import build_model
-from mindocr.utils.logger import Logger
+from mindocr.utils.logger import set_logger
 from mindocr.utils.visualize import show_imgs
 
 # map algorithm name to model name (which can be checked by `mindocr.list_models()`)
@@ -35,7 +36,7 @@
     "RARE_CH": "rare_resnet34_ch",
     "SVTR": "svtr_tiny",
 }
-_logger = Logger("mindocr")
+logger = logging.getLogger("mindocr")
 
 
 class TextRecognizer(object):
@@ -43,7 +44,7 @@ def __init__(self, args):
         self.batch_num = args.rec_batch_num
         self.batch_mode = args.rec_batch_mode
         # self.batch_mode = args.rec_batch_mode and (self.batch_num > 1)
-        _logger.info(
+        logger.info(
             "recognize in {} mode {}".format(
                 "batch" if self.batch_mode else "serial",
                 "batch_size: " + str(self.batch_num) if self.batch_mode else "",
@@ -67,7 +68,7 @@ def __init__(self, args):
         # amp_level = 'O2' if args.rec_algorithm.startswith('SVTR') else args.rec_amp_level
         amp_level = args.rec_amp_level
         if args.rec_algorithm.startswith("SVTR") and amp_level != "O2":
-            _logger.warning(
+            logger.warning(
                 "SVTR recognition model is optimized for amp_level O2. ampl_level for rec model is changed to O2"
             )
             amp_level = "O2"
@@ -78,7 +79,7 @@ def __init__(self, args):
         self.cast_pred_fp32 = amp_level != "O0"
         if self.cast_pred_fp32:
             self.cast = ops.Cast()
-        _logger.info(
+        logger.info(
             "Init recognition model: {} --> {}. Model weights loaded from {}".format(
                 args.rec_algorithm, model_name, "pretrained url" if pretrained else ckpt_load_path
             )
@@ -117,7 +118,7 @@ def __call__(self, img_or_path_list: list, do_visualize=False):
         """
 
         assert isinstance(img_or_path_list, list), "Input for text recognition must be list of images or image paths."
-        _logger.info(f"num images for rec: {len(img_or_path_list)}")
+        logger.info(f"num images for rec: {len(img_or_path_list)}")
         if self.batch_mode:
             rec_res_all_crops = self.run_batchwise(img_or_path_list, do_visualize)
         else:
@@ -148,7 +149,7 @@ def run_batchwise(self, img_or_path_list: list, do_visualize=False):
         for idx in range(0, num_imgs, self.batch_num):  # batch begin index i
             batch_begin = idx
             batch_end = min(idx + self.batch_num, num_imgs)
-            _logger.info(f"Rec img idx range: [{batch_begin}, {batch_end})")
+            logger.info(f"Rec img idx range: [{batch_begin}, {batch_end})")
             # TODO: set max_wh_ratio to the maximum wh ratio of images in the batch. and update it for resize,
             #  which may improve recognition accuracy in batch-mode
             # especially for long text image. max_wh_ratio=max(max_wh_ratio, img_w / img_h).
@@ -215,8 +216,8 @@ def run_single(self, img_or_path, crop_idx=0, do_visualize=True):
                 show=False,
                 save_path=os.path.join(self.vis_dir, fn + "_rec_preproc.png"),
             )
-        _logger.info(f"Origin image shape: {data['image_ori'].shape}")
-        _logger.info(f"Preprocessed image shape: {data['image'].shape}")
+        logger.info(f"Origin image shape: {data['image_ori'].shape}")
+        logger.info(f"Preprocessed image shape: {data['image'].shape}")
 
         # infer
         input_np = data["image"]
@@ -237,7 +238,7 @@ def run_single(self, img_or_path, crop_idx=0, do_visualize=True):
 
         rec_res = (rec_res["texts"][0], rec_res["confs"][0])
 
-        _logger.info(f"Crop {crop_idx} rec result: {rec_res}")
+        logger.info(f"Crop {crop_idx} rec result: {rec_res}")
 
         return rec_res
 
@@ -261,6 +262,7 @@ def save_rec_res(rec_res_all, img_paths, include_score=False, save_path="./rec_r
 if __name__ == "__main__":
     # parse args
     args = parse_args()
+    set_logger(name="mindocr")
     save_dir = args.draw_img_save_dir
     img_paths = get_image_paths(args.image_dir)
     # uncomment it to quick test the infer FPS
@@ -280,6 +282,6 @@ def save_rec_res(rec_res_all, img_paths, include_score=False, save_path="./rec_r
     # save all results in a txt file
     save_fp = os.path.join(save_dir, "rec_results.txt" if args.rec_batch_mode else "rec_results_serial.txt")
     save_rec_res(rec_res_all, img_paths, save_path=save_fp)
-    print("All rec res: ", rec_res_all)
-    print("Done! Text recognition results saved in ", save_dir)
-    print("Time cost: ", t, "FPS: ", len(img_paths) / t)
+    logger.info(f"All rec res: {rec_res_all}")
+    logger.info(f"Done! Text recognition results saved in {save_dir}")
+    logger.info(f"Time cost: {t}, FPS: {len(img_paths) / t}")
diff --git a/tools/infer/text/predict_system.py b/tools/infer/text/predict_system.py
index 3a76e6d4c..372f84f6a 100644
--- a/tools/infer/text/predict_system.py
+++ b/tools/infer/text/predict_system.py
@@ -9,6 +9,7 @@
 """
 
 import json
+import logging
 import os
 import sys
 from time import time
@@ -26,10 +27,10 @@
 __dir__ = os.path.dirname(os.path.abspath(__file__))
 sys.path.insert(0, os.path.abspath(os.path.join(__dir__, "../../../")))
 
-from mindocr.utils.logger import Logger
+from mindocr.utils.logger import set_logger
 from mindocr.utils.visualize import visualize  # noqa
 
-_logger = Logger("mindocr")
+logger = logging.getLogger("mindocr")
 
 
 class TextSystem(object):
@@ -73,7 +74,7 @@ def __call__(self, img_or_path: Union[str, np.ndarray], do_visualize=True):
         det_res, data = self.text_detect(img_or_path, do_visualize=False)
         time_profile["det"] = time() - start
         polys = det_res["polys"].copy()
-        _logger.info(f"Num detected text boxes: {len(polys)}\nDet time: {time_profile['det']}")
+        logger.info(f"Num detected text boxes: {len(polys)}\nDet time: {time_profile['det']}")
 
         # crop text regions
         crops = []
@@ -91,7 +92,7 @@ def __call__(self, img_or_path: Union[str, np.ndarray], do_visualize=True):
         rec_res_all_crops = self.text_recognize(crops, do_visualize=False)
         time_profile["rec"] = time() - rs
 
-        _logger.info(
+        logger.info(
             "Recognized texts: \n"
             + "\n".join([f"{text}\t{score}" for text, score in rec_res_all_crops])
             + f"\nRec time: {time_profile['rec']}"
@@ -155,6 +156,7 @@ def save_res(boxes_all, text_scores_all, img_paths, save_path="system_results.tx
 def main():
     # parse args
     args = parse_args()
+    set_logger(name="mindocr")
     save_dir = args.draw_img_save_dir
     img_paths = get_image_paths(args.image_dir)
 
@@ -175,7 +177,7 @@ def main():
     tot_time = {}  # {'det': 0, 'rec': 0, 'all': 0}
     boxes_all, text_scores_all = [], []
     for i, img_path in enumerate(img_paths):
-        print(f"\nINFO: Infering [{i+1}/{len(img_paths)}]: ", img_path)
+        logger.info(f"\nINFO: Infering [{i+1}/{len(img_paths)}]: {img_path}")
         boxes, text_scores, time_prof = text_spot(img_path, do_visualize=args.visualize_output)
         boxes_all.append(boxes)
         text_scores_all.append(text_scores)
@@ -187,14 +189,14 @@ def main():
                 tot_time[k] += time_prof[k]
 
     fps = len(img_paths) / tot_time["all"]
-    print("Total time:", tot_time["all"])
-    print("Average FPS: ", fps)
+    logger.info(f"Total time:{tot_time['all']}")
+    logger.info(f"Average FPS: {fps}")
     avg_time = {k: tot_time[k] / len(img_paths) for k in tot_time}
-    print("Averge time cost: ", avg_time)
+    logger.info(f"Averge time cost: {avg_time}")
 
     # save result
     save_res(boxes_all, text_scores_all, img_paths, save_path=os.path.join(save_dir, "system_results.txt"))
-    print("Done! Results saved in ", os.path.join(save_dir, "system_results.txt"))
+    logger.info(f"Done! Results saved in {os.path.join(save_dir, 'system_results.txt')}")
 
 
 if __name__ == "__main__":
diff --git a/tools/infer/text/preprocess.py b/tools/infer/text/preprocess.py
index 219559232..9a97efbb3 100644
--- a/tools/infer/text/preprocess.py
+++ b/tools/infer/text/preprocess.py
@@ -1,3 +1,4 @@
+import logging
 import os
 import sys
 
@@ -7,9 +8,8 @@
 
 from mindocr.data.constants import IMAGENET_DEFAULT_MEAN, IMAGENET_DEFAULT_STD
 from mindocr.data.transforms import create_transforms, run_transforms
-from mindocr.utils.logger import Logger
 
-_logger = Logger("mindocr")
+_logger = logging.getLogger("mindocr")
 
 
 class Preprocessor(object):
diff --git a/tools/infer/text/utils.py b/tools/infer/text/utils.py
index 9c225ae56..e13ce0cdc 100644
--- a/tools/infer/text/utils.py
+++ b/tools/infer/text/utils.py
@@ -1,4 +1,5 @@
 import glob
+import logging
 import os
 from pathlib import Path
 from typing import List
@@ -6,9 +7,7 @@
 import cv2
 import numpy as np
 
-from mindocr.utils.logger import Logger
-
-_logger = Logger("mindocr")
+_logger = logging.getLogger("mindocr")
 
 
 def get_image_paths(img_dir: str) -> List[str]:
diff --git a/tools/modelarts_adapter/modelarts.py b/tools/modelarts_adapter/modelarts.py
index 7fa979111..d62ae2348 100644
--- a/tools/modelarts_adapter/modelarts.py
+++ b/tools/modelarts_adapter/modelarts.py
@@ -1,14 +1,13 @@
 import functools
+import logging
 import os
 import subprocess
 import sys
 import time
 from typing import Any, Callable, Dict, List, Union
 
-from mindocr.utils.logger import Logger
-
 LOCAL_RANK = int(os.getenv("RANK_ID", 0))
-_logger = Logger("mindocr")
+_logger = logging.getLogger("mindocr.tools.modelarts")
 
 _global_sync_count = 0
 
diff --git a/tools/train.py b/tools/train.py
index c900a307a..18ff4d1e9 100644
--- a/tools/train.py
+++ b/tools/train.py
@@ -1,6 +1,7 @@
 """
 Model training
 """
+import logging
 import os
 import shutil
 import sys
@@ -28,12 +29,14 @@
 from mindocr.utils.callbacks import EvalSaveCallback
 from mindocr.utils.checkpoint import resume_train_network
 from mindocr.utils.ema import EMA
-from mindocr.utils.logger import get_logger
+from mindocr.utils.logger import set_logger
 from mindocr.utils.loss_scaler import get_loss_scales
 from mindocr.utils.model_wrapper import NetWithLossWrapper
 from mindocr.utils.seed import set_seed
 from mindocr.utils.train_step_wrapper import TrainOneStepWrapper
 
+logger = logging.getLogger("mindocr.train")
+
 
 def main(cfg):
     # init env
@@ -48,29 +51,39 @@ def main(cfg):
             gradients_mean=True,
             # parameter_broadcast=True,
         )
+        # create logger, only rank0 log will be output to the screen
+        set_logger(
+            name="mindocr",
+            output_dir=cfg.train.ckpt_save_dir,
+            rank=rank_id,
+            log_level=eval(cfg.system.get("log_level", "logging.INFO")),
+        )
     else:
         device_num = None
         rank_id = None
+
+        # create logger, only rank0 log will be output to the screen
+        set_logger(
+            name="mindocr",
+            output_dir=cfg.train.ckpt_save_dir,
+            rank=0,
+            log_level=eval(cfg.system.get("log_level", "logging.INFO")),
+        )
         if "DEVICE_ID" in os.environ:
-            print(
-                f"INFO: Standalone training. Device id: {os.environ.get('DEVICE_ID')}, "
+            logger.info(
+                f"Standalone training. Device id: {os.environ.get('DEVICE_ID')}, "
                 f"specified by environment variable 'DEVICE_ID'."
             )
         else:
             device_id = cfg.system.get("device_id", 0)
             ms.set_context(device_id=device_id)
-            print(
-                f"INFO: Standalone training. Device id: {device_id}, "
+            logger.info(
+                f"Standalone training. Device id: {device_id}, "
                 f"specified by system.device_id in yaml config file or is default value 0."
             )
 
     set_seed(cfg.system.seed)
 
-    is_main_device = rank_id in [None, 0]
-
-    # create logger, only rank0 log will be output to the screen
-    logger = get_logger(log_dir=cfg.train.ckpt_save_dir, rank=rank_id)
-
     # create dataset
     loader_train = build_dataset(
         cfg.train.dataset,
@@ -166,7 +179,6 @@ def main(cfg):
         pred_cast_fp32=(amp_level != "O0"),
         rank_id=rank_id,
         device_num=device_num,
-        logger=logger,
         batch_size=cfg.train.loader.batch_size,
         ckpt_save_dir=cfg.train.ckpt_save_dir,
         main_indicator=cfg.metric.main_indicator,
@@ -218,7 +230,7 @@ def main(cfg):
     )
 
     # save args used for training
-    if is_main_device:
+    if rank_id in [None, 0]:
         with open(os.path.join(cfg.train.ckpt_save_dir, "args.yaml"), "w") as f:
             args_text = yaml.safe_dump(cfg.to_dict(), default_flow_style=False, sort_keys=False)
             f.write(args_text)


Test patch:
diff --git a/tests/ut/test_logger.py b/tests/ut/test_logger.py
index 91546e39b..5e453d0b8 100644
--- a/tests/ut/test_logger.py
+++ b/tests/ut/test_logger.py
@@ -6,7 +6,7 @@
 import yaml
 from addict import Dict
 
-from mindocr.utils.logger import get_logger
+from mindocr.utils.logger import set_logger
 
 
 @pytest.mark.parametrize("task", ["det", "rec"])
@@ -20,4 +20,4 @@ def test_logger(task):
         cfg = yaml.safe_load(fp)
     cfg = Dict(cfg)
 
-    get_logger(cfg.train.ckpt_save_dir, rank=0)
+    set_logger(name="mindocr", output_dir=cfg.train.ckpt_save_dir, rank=0)