You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

logger.py 7.6 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. # -*- coding: utf-8 -*-
  2. # MegEngine is Licensed under the Apache License, Version 2.0 (the "License")
  3. #
  4. # Copyright (c) 2014-2021 Megvii Inc. All rights reserved.
  5. #
  6. # Unless required by applicable law or agreed to in writing,
  7. # software distributed under the License is distributed on an
  8. # "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9. import contextlib
  10. import logging
  11. import os
  12. import sys
  13. _all_loggers = []
  14. _default_level_name = os.getenv("MEGENGINE_LOGGING_LEVEL", "INFO")
  15. _default_level = logging.getLevelName(_default_level_name.upper())
  16. def set_log_file(fout, mode="a"):
  17. r"""
  18. Sets log output file.
  19. :type fout: str or file-like
  20. :param fout: file-like object that supports write and flush, or string for
  21. the filename
  22. :type mode: str
  23. :param mode: specify the mode to open log file if *fout* is a string
  24. """
  25. if isinstance(fout, str):
  26. fout = open(fout, mode)
  27. MegEngineLogFormatter.log_fout = fout
  28. class MegEngineLogFormatter(logging.Formatter):
  29. log_fout = None
  30. date_full = "[%(asctime)s %(lineno)d@%(filename)s:%(name)s] "
  31. date = "%(asctime)s "
  32. msg = "%(message)s"
  33. max_lines = 256
  34. def _color_exc(self, msg):
  35. r"""
  36. Sets the color of message as the execution type.
  37. """
  38. return "\x1b[34m{}\x1b[0m".format(msg)
  39. def _color_dbg(self, msg):
  40. r"""
  41. Sets the color of message as the debugging type.
  42. """
  43. return "\x1b[36m{}\x1b[0m".format(msg)
  44. def _color_warn(self, msg):
  45. r"""
  46. Sets the color of message as the warning type.
  47. """
  48. return "\x1b[1;31m{}\x1b[0m".format(msg)
  49. def _color_err(self, msg):
  50. r"""
  51. Sets the color of message as the error type.
  52. """
  53. return "\x1b[1;4;31m{}\x1b[0m".format(msg)
  54. def _color_omitted(self, msg):
  55. r"""
  56. Sets the color of message as the omitted type.
  57. """
  58. return "\x1b[35m{}\x1b[0m".format(msg)
  59. def _color_normal(self, msg):
  60. r"""
  61. Sets the color of message as the normal type.
  62. """
  63. return msg
  64. def _color_date(self, msg):
  65. r"""
  66. Sets the color of message the same as date.
  67. """
  68. return "\x1b[32m{}\x1b[0m".format(msg)
  69. def format(self, record):
  70. if record.levelno == logging.DEBUG:
  71. mcl, mtxt = self._color_dbg, "DBG"
  72. elif record.levelno == logging.WARNING:
  73. mcl, mtxt = self._color_warn, "WRN"
  74. elif record.levelno == logging.ERROR:
  75. mcl, mtxt = self._color_err, "ERR"
  76. else:
  77. mcl, mtxt = self._color_normal, ""
  78. if mtxt:
  79. mtxt += " "
  80. if self.log_fout:
  81. self.__set_fmt(self.date_full + mtxt + self.msg)
  82. formatted = super(MegEngineLogFormatter, self).format(record)
  83. nr_line = formatted.count("\n") + 1
  84. if nr_line >= self.max_lines:
  85. head, body = formatted.split("\n", 1)
  86. formatted = "\n".join(
  87. [
  88. head,
  89. "BEGIN_LONG_LOG_{}_LINES{{".format(nr_line - 1),
  90. body,
  91. "}}END_LONG_LOG_{}_LINES".format(nr_line - 1),
  92. ]
  93. )
  94. self.log_fout.write(formatted)
  95. self.log_fout.write("\n")
  96. self.log_fout.flush()
  97. self.__set_fmt(self._color_date(self.date) + mcl(mtxt + self.msg))
  98. formatted = super(MegEngineLogFormatter, self).format(record)
  99. if record.exc_text or record.exc_info:
  100. # handle exception format
  101. b = formatted.find("Traceback ")
  102. if b != -1:
  103. s = formatted[b:]
  104. s = self._color_exc(" " + s.replace("\n", "\n "))
  105. formatted = formatted[:b] + s
  106. nr_line = formatted.count("\n") + 1
  107. if nr_line >= self.max_lines:
  108. lines = formatted.split("\n")
  109. remain = self.max_lines // 2
  110. removed = len(lines) - remain * 2
  111. if removed > 0:
  112. mid_msg = self._color_omitted(
  113. "[{} log lines omitted (would be written to output file "
  114. "if set_log_file() has been called;\n"
  115. " the threshold can be set at "
  116. "MegEngineLogFormatter.max_lines)]".format(removed)
  117. )
  118. formatted = "\n".join(lines[:remain] + [mid_msg] + lines[-remain:])
  119. return formatted
  120. if sys.version_info.major < 3:
  121. def __set_fmt(self, fmt):
  122. self._fmt = fmt
  123. else:
  124. def __set_fmt(self, fmt):
  125. self._style._fmt = fmt
  126. def get_logger(name=None, formatter=MegEngineLogFormatter):
  127. r"""
  128. Gets megengine logger with given name.
  129. """
  130. logger = logging.getLogger(name)
  131. if getattr(logger, "_init_done__", None):
  132. return logger
  133. logger._init_done__ = True
  134. logger.propagate = False
  135. logger.setLevel(_default_level)
  136. handler = logging.StreamHandler()
  137. handler.setFormatter(formatter(datefmt="%d %H:%M:%S"))
  138. handler.setLevel(0)
  139. del logger.handlers[:]
  140. logger.addHandler(handler)
  141. _all_loggers.append(logger)
  142. return logger
  143. def set_log_level(level, update_existing=True):
  144. """
  145. Sets default logging level.
  146. :type level: int e.g. logging.INFO
  147. :param level: loggin level given by python :mod:`logging` module
  148. :param update_existing: whether to update existing loggers
  149. """
  150. global _default_level # pylint: disable=global-statement
  151. _default_level = level
  152. if update_existing:
  153. for i in _all_loggers:
  154. i.setLevel(level)
  155. _logger = get_logger(__name__)
  156. try:
  157. if sys.version_info.major < 3:
  158. raise ImportError()
  159. from .core._imperative_rt.utils import Logger as _imperative_rt_logger
  160. class MegBrainLogFormatter(MegEngineLogFormatter):
  161. date = "%(asctime)s[mgb] "
  162. def _color_date(self, msg):
  163. return "\x1b[33m{}\x1b[0m".format(msg)
  164. _megbrain_logger = get_logger("megbrain", MegBrainLogFormatter)
  165. _imperative_rt_logger.set_log_handler(_megbrain_logger)
  166. def set_mgb_log_level(level):
  167. r"""
  168. Sets megbrain log level
  169. :type level: int e.g. logging.INFO
  170. :param level: new log level
  171. :return: original log level
  172. """
  173. _megbrain_logger.setLevel(level)
  174. if level == logging.getLevelName("ERROR"):
  175. rst = _imperative_rt_logger.set_log_level(
  176. _imperative_rt_logger.LogLevel.Error
  177. )
  178. elif level == logging.getLevelName("INFO"):
  179. rst = _imperative_rt_logger.set_log_level(
  180. _imperative_rt_logger.LogLevel.Info
  181. )
  182. else:
  183. rst = _imperative_rt_logger.set_log_level(
  184. _imperative_rt_logger.LogLevel.Debug
  185. )
  186. return rst
  187. set_mgb_log_level(_default_level)
  188. except ImportError as exc:
  189. def set_mgb_log_level(level):
  190. raise NotImplementedError("imperative_rt has not been imported")
  191. @contextlib.contextmanager
  192. def replace_mgb_log_level(level):
  193. r"""
  194. Replaces megbrain log level in a block and restore after exiting.
  195. :type level: int e.g. logging.INFO
  196. :param level: new log level
  197. """
  198. old = set_mgb_log_level(level)
  199. try:
  200. yield
  201. finally:
  202. set_mgb_log_level(old)
  203. def enable_debug_log():
  204. r"""
  205. Sets logging level to debug for all components.
  206. """
  207. set_log_level(logging.DEBUG)
  208. set_mgb_log_level(logging.DEBUG)

MegEngine 安装包中集成了使用 GPU 运行代码所需的 CUDA 环境,不用区分 CPU 和 GPU 版。 如果想要运行 GPU 程序,请确保机器本身配有 GPU 硬件设备并安装好驱动。 如果你想体验在云端 GPU 算力平台进行深度学习开发的感觉,欢迎访问 MegStudio 平台