[PYTHON] 파이썬의 로깅 형식이 메시지 로그 수준에 따라 수정 될 수 있습니까?
PYTHON파이썬의 로깅 형식이 메시지 로그 수준에 따라 수정 될 수 있습니까?
파이썬의 로깅 메커니즘을 사용하여 출력을 화면에 출력하고 있습니다. print 문을 사용하여이 작업을 수행 할 수 있지만 사용자가 특정 유형의 출력을 사용하지 않도록 미세 조정 된 세분화를 허용하려고합니다. 나는 오류에 대해 인쇄 된 형식을 좋아하지만 출력 수준이 "정보"일 때 더 간단한 형식을 선호합니다.
예 :
logger.error("Running cmd failed")
logger.info("Running cmd passed")
이 예제에서는 오류 형식을 다르게 인쇄하고 싶습니다.
여러 로깅 개체가 없어도 서로 다른 로그 수준에 다른 형식을 사용할 수 있습니까? 로거가 수정되면 로거를 수정하지 않고이 작업을 수행하기를 원합니다. 출력이 로깅되는 방식을 결정하는 if / else 문 수가 많기 때문입니다.
해결법
-
==============================
1.예, 사용자 정의 Formatter 클래스를 사용하여이 작업을 수행 할 수 있습니다.
예, 사용자 정의 Formatter 클래스를 사용하여이 작업을 수행 할 수 있습니다.
class MyFormatter(logging.Formatter): def format(self, record): #compute s according to record.levelno #for example, by setting self._fmt #according to the levelno, then calling #the superclass to do the actual formatting return s
그런 다음 MyFormatter 인스턴스를 핸들러에 연결하십시오.
-
==============================
2.방금이 문제에 직면했고 위의 예에서 남겨진 "구멍"을 채우는 데 문제가있었습니다. 여기에 내가 사용한보다 완벽하고 효과적인 버전이 있습니다. 희망적으로 이는 누군가에게 도움이되기를 바랍니다.
방금이 문제에 직면했고 위의 예에서 남겨진 "구멍"을 채우는 데 문제가있었습니다. 여기에 내가 사용한보다 완벽하고 효과적인 버전이 있습니다. 희망적으로 이는 누군가에게 도움이되기를 바랍니다.
# Custom formatter class MyFormatter(logging.Formatter): err_fmt = "ERROR: %(msg)s" dbg_fmt = "DBG: %(module)s: %(lineno)d: %(msg)s" info_fmt = "%(msg)s" def __init__(self, fmt="%(levelno)s: %(msg)s"): logging.Formatter.__init__(self, fmt) def format(self, record): # Save the original format configured by the user # when the logger formatter was instantiated format_orig = self._fmt # Replace the original format with one customized by logging level if record.levelno == logging.DEBUG: self._fmt = MyFormatter.dbg_fmt elif record.levelno == logging.INFO: self._fmt = MyFormatter.info_fmt elif record.levelno == logging.ERROR: self._fmt = MyFormatter.err_fmt # Call the original formatter class to do the grunt work result = logging.Formatter.format(self, record) # Restore the original format configured by the user self._fmt = format_orig return result
편집하다:
Halloleo의 칭찬은 스크립트에 위의 내용을 사용하는 방법에 대한 예입니다.
fmt = MyFormatter() hdlr = logging.StreamHandler(sys.stdout) hdlr.setFormatter(fmt) logging.root.addHandler(hdlr) logging.root.setLevel(DEBUG)
편집 2 :
Python3 로깅이 조금 변경되었습니다. Python3 접근법을 보려면 여기를 참조하십시오.
-
==============================
3.그리고 JS 답은 비슷하지만 좀 더 콤팩트합니다.
그리고 JS 답은 비슷하지만 좀 더 콤팩트합니다.
class SpecialFormatter(logging.Formatter): FORMATS = {logging.DEBUG :"DBG: %(module)s: %(lineno)d: %(message)s", logging.ERROR : "ERROR: %(message)s", logging.INFO : "%(message)s", 'DEFAULT' : "%(levelname)s: %(message)s"} def format(self, record): self._fmt = self.FORMATS.get(record.levelno, self.FORMATS['DEFAULT']) return logging.Formatter.format(self, record) hdlr = logging.StreamHandler(sys.stderr) hdlr.setFormatter(SpecialFormatter()) logging.root.addHandler(hdlr) logging.root.setLevel(logging.INFO)
-
==============================
4.이는 로깅의 새로운 구현에 대한 estani의 대답에 대한 적응입니다. 이제 형식화 스타일에 의존하는 형식화 프로그램입니다. 광산은 '{'스타일 형식을 사용하지만 적응할 수 있습니다. 좀 더 일반적인 것으로 세련되고 __init__에 인자로 서식 스타일과 커스텀 메시지를 선택할 수 있습니다.
이는 로깅의 새로운 구현에 대한 estani의 대답에 대한 적응입니다. 이제 형식화 스타일에 의존하는 형식화 프로그램입니다. 광산은 '{'스타일 형식을 사용하지만 적응할 수 있습니다. 좀 더 일반적인 것으로 세련되고 __init__에 인자로 서식 스타일과 커스텀 메시지를 선택할 수 있습니다.
class SpecialFormatter(logging.Formatter): FORMATS = {logging.DEBUG : logging._STYLES['{']("{module} DEBUG: {lineno}: {message}"), logging.ERROR : logging._STYLES['{']("{module} ERROR: {message}"), logging.INFO : logging._STYLES['{']("{module}: {message}"), 'DEFAULT' : logging._STYLES['{']("{module}: {message}")} def format(self, record): # Ugly. Should be better self._style = self.FORMATS.get(record.levelno, self.FORMATS['DEFAULT']) return logging.Formatter.format(self, record) hdlr = logging.StreamHandler(sys.stderr) hdlr.setFormatter(SpecialFormatter()) logging.root.addHandler(hdlr) logging.root.setLevel(logging.INFO)
-
==============================
5.스타일이나 내부 필드를 사용하는 대신 record.levelno (또는 다른 기준)에 따라 다른 포맷터를 위임하는 Formatter를 만들 수도 있습니다. 이것은 나의 겸허 한 의견에서 약간 더 깨끗한 해결책이다. 아래 코드는 파이썬 버전> = 2.7 이상에서 작동합니다 :
스타일이나 내부 필드를 사용하는 대신 record.levelno (또는 다른 기준)에 따라 다른 포맷터를 위임하는 Formatter를 만들 수도 있습니다. 이것은 나의 겸허 한 의견에서 약간 더 깨끗한 해결책이다. 아래 코드는 파이썬 버전> = 2.7 이상에서 작동합니다 :
간단한 방법은 다음과 같이 보일 것입니다 :
class MyFormatter(logging.Formatter): default_fmt = logging.Formatter('%(levelname)s in %(name)s: %(message)s') info_fmt = logging.Formatter('%(message)s') def format(self, record): if record.levelno == logging.INFO: return self.info_fmt.format(record) else: return self.default_fmt.format(record)
하지만 좀 더 일반적인 것으로 만들 수 있습니다.
class VarFormatter(logging.Formatter): default_formatter = logging.Formatter('%(levelname)s in %(name)s: %(message)s') def __init__(self, formats): """ formats is a dict { loglevel : logformat } """ self.formatters = {} for loglevel in formats: self.formatters[loglevel] = logging.Formatter(formats[loglevel]) def format(self, record): formatter = self.formatters.get(record.levelno, self.default_formatter) return formatter.format(record)
여기서 입력으로 딕테이션을 사용했지만 분명히 보트를 뜨는 튜플이나 kwargs도 사용할 수 있습니다. 그러면 다음과 같이 사용됩니다.
formatter = VarFormatter({logging.INFO: '[%(message)s]', logging.WARNING: 'warning: %(message)s'}) <... attach formatter to logger ...>
-
==============================
6.위의 솔루션은 3.3.3 릴리스와 함께 작동합니다. 그러나 3.3.4를 사용하면 다음 오류가 발생합니다.
위의 솔루션은 3.3.3 릴리스와 함께 작동합니다. 그러나 3.3.4를 사용하면 다음 오류가 발생합니다.
FORMATS = { logging.DEBUG : logging._STYLES['{']("{module} DEBUG: {lineno}: {message}"),
TypeError : 'tuple'객체를 호출 할 수 없습니다.
로깅 클래스에서 주위를 검색 한 후 Lib \ logging__init __. py 데이터 구조가 3.3.3에서 3.3.4로 변경되어 문제가 발생 함을 발견했습니다.
_STYLES = { '%': PercentStyle, '{': StrFormatStyle, '$': StringTemplateStyle }
_STYLES = { '%': (PercentStyle, BASIC_FORMAT), '{': (StrFormatStyle, '{levelname}:{name}:{message} AA'), '$': (StringTemplateStyle, '${levelname}:${name}:${message} BB'), }
따라서 업데이트 된 솔루션은
class SpecialFormatter(logging.Formatter): FORMATS = {logging.DEBUG : logging._STYLES['{'][0]("{module} DEBUG: {lineno}: {message}"), logging.ERROR : logging._STYLES['{'][0]("{module} ERROR: {message}"), logging.INFO : logging._STYLES['{'][0]("{module}: {message}"), 'DEFAULT' : logging._STYLES['{'][0]("{module}: {message}")} def format(self, record): # Ugly. Should be better self._style = self.FORMATS.get(record.levelno, self.FORMATS['DEFAULT']) return logging.Formatter.format(self, record)
-
==============================
7.특정 수준의 서식을 건너 뛰려는 경우 다음과 같은 다른 대답보다 간단한 것을 할 수 있습니다.
특정 수준의 서식을 건너 뛰려는 경우 다음과 같은 다른 대답보다 간단한 것을 할 수 있습니다.
class FormatterNotFormattingInfo(logging.Formatter): def __init__(self, fmt = '%(levelname)s:%(message)s'): logging.Formatter.__init__(self, fmt) def format(self, record): if record.levelno == logging.INFO: return record.getMessage() return logging.Formatter.format(self, record)
이것은 또한 self._fmt 나 self._style과 같은 내부 변수를 사용하지 않음으로써 3.2 릴리스 전과 후에 작업 할 수 있다는 이점이 있습니다.
from https://stackoverflow.com/questions/1343227/can-pythons-logging-format-be-modified-depending-on-the-message-log-level by cc-by-sa and MIT license
'PYTHON' 카테고리의 다른 글
[PYTHON] Python datetime strptime () 및 strftime () : 표준 시간대 정보 보존 방법 (0) | 2018.10.18 |
---|---|
[PYTHON] 정확히 PYTHONPATH에 무엇을 설정해야합니까? (0) | 2018.10.18 |
[PYTHON] ValueError : 닫힌 파일에 대한 I / O 작업 (0) | 2018.10.18 |
[PYTHON] 파이썬에서 정수가 불변 인 이유는 무엇입니까? [복제] (0) | 2018.10.18 |
[PYTHON] 파이썬 로거로 하여금 로그 파일 외에도 모든 메시지를 표준 출력으로 출력하도록합니다. (0) | 2018.10.18 |