logging.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. # -*- coding: utf-8 -*-
  2. # @Time : 2020/6/15 14:25
  3. # @Author : zhoujun
  4. import logging
  5. import torch.distributed as dist
  6. logger_initialized = {}
  7. def get_logger(name, log_file=None, log_level=logging.INFO):
  8. """Initialize and get a logger by name.
  9. If the logger has not been initialized, this method will initialize the
  10. logger by adding one or two handlers, otherwise the initialized logger will
  11. be directly returned. During initialization, a StreamHandler will always be
  12. added. If `log_file` is specified and the process rank is 0, a FileHandler
  13. will also be added.
  14. Args:
  15. name (str): Logger name.
  16. log_file (str | None): The log filename. If specified, a FileHandler
  17. will be added to the logger.
  18. log_level (int): The logger level. Note that only the process of
  19. rank 0 is affected, and other processes will set the level to
  20. "Error" thus be silent most of the time.
  21. Returns:
  22. logging.Logger: The expected logger.
  23. """
  24. logger = logging.getLogger(name)
  25. if name in logger_initialized:
  26. return logger
  27. # handle hierarchical names
  28. # e.g., logger "a" is initialized, then logger "a.b" will skip the
  29. # initialization since it is a child of "a".
  30. for logger_name in logger_initialized:
  31. if name.startswith(logger_name):
  32. return logger
  33. stream_handler = logging.StreamHandler()
  34. handlers = [stream_handler]
  35. if dist.is_available() and dist.is_initialized():
  36. rank = dist.get_rank()
  37. else:
  38. rank = 0
  39. # only rank 0 will add a FileHandler
  40. if rank == 0 and log_file is not None:
  41. file_handler = logging.FileHandler(log_file, 'w')
  42. handlers.append(file_handler)
  43. formatter = logging.Formatter(
  44. '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
  45. for handler in handlers:
  46. handler.setFormatter(formatter)
  47. handler.setLevel(log_level)
  48. logger.addHandler(handler)
  49. if rank == 0:
  50. logger.setLevel(log_level)
  51. else:
  52. logger.setLevel(logging.ERROR)
  53. logger_initialized[name] = True
  54. return logger
  55. def print_log(msg, logger=None, level=logging.INFO):
  56. """Print a log message.
  57. Args:
  58. msg (str): The message to be logged.
  59. logger (logging.Logger | str | None): The logger to be used.
  60. Some special loggers are:
  61. - "silent": no message will be printed.
  62. - other str: the logger obtained with `get_root_logger(logger)`.
  63. - None: The `print()` method will be used to print log messages.
  64. level (int): Logging level. Only available when `logger` is a Logger
  65. object or "root".
  66. """
  67. if logger is None:
  68. print(msg)
  69. elif isinstance(logger, logging.Logger):
  70. logger.log(level, msg)
  71. elif logger == 'silent':
  72. pass
  73. elif isinstance(logger, str):
  74. _logger = get_logger(logger)
  75. _logger.log(level, msg)
  76. else:
  77. raise TypeError(
  78. 'logger should be either a logging.Logger object, str, '
  79. f'"silent" or None, but got {type(logger)}')