단일 파일을 사용한 Python Logging(함수 이름, 파일 이름, 줄 번호)
저는 애플리케이션이 어떻게 작동하는지 배우려고 노력하고 있습니다.그리고 이를 위해 각 함수 본문의 첫 번째 줄로 debug 명령을 삽입하여 함수의 이름과 로그 출력으로 메시지를 보내는 줄 번호(코드 내)를 기록합니다.마지막으로, 이 응용 프로그램은 많은 파일로 구성되어 있기 때문에 응용 프로그램의 제어 흐름을 더 잘 이해할 수 있도록 단일 로그 파일을 만들고 싶습니다.
제가 알고 있는 것은 다음과 같습니다.
함수 이름을 가져오는 데 사용할 수 있습니다.
function_name.__name__
하지만 일반 파일을 빠르게 복사하고 붙여넣을 수 있도록 function_name을 사용하고 싶지 않습니다.Log.info("Message")
모든 함수의 본문에서).나는 이것이 C에서 할 수 있다는 것을 압니다.__func__
매크로 하지만 파이썬에 대해서는 잘 모르겠습니다.파일 이름과 줄 번호를 얻기 위해, 나는 내 애플리케이션이 파이썬을 사용하는 것을 보았다 (그리고 나는 믿는다).
locals()
기능을 하지만 내가 완전히 알지 못하는 구문으로. 예:options = "LOG.debug('%(flag)s : %(flag_get)s' % locals())
그리고 다음과 같은 것을 사용해 보았습니다.LOG.info("My message %s" % locals())
그것은 다음과 같은 것을 생산합니다.{'self': <__main__.Class_name object at 0x22f8cd0>}
이것에 대한 의견이 있으십니까?저는 로깅을 사용하는 방법을 알고 파일에 로그할 핸들러를 추가하지만 프로젝트에서 모든 로그 메시지를 함수 호출의 올바른 순서로 기록하는 데 단일 파일을 사용할 수 있는지는 잘 모르겠습니다.
정답은 이미 제공된 변수를 사용하는 것입니다.
import logging
logger = logging.getLogger(__name__)
FORMAT = "[%(filename)s:%(lineno)s - %(funcName)20s() ] %(message)s"
logging.basicConfig(format=FORMAT)
logger.setLevel(logging.DEBUG)
원하는 곳에 다음을 추가하면 됩니다.
logger.debug('your message')
현재 작업 중인 스크립트의 출력 예:
[invRegex.py:150 - handleRange() ] ['[A-Z]']
[invRegex.py:155 - handleRepetition() ] [[<__main__.CharacterRangeEmitter object at 0x10ba03050>, '{', '1', '}']]
[invRegex.py:197 - handleMacro() ] ['\\d']
[invRegex.py:155 - handleRepetition() ] [[<__main__.CharacterRangeEmitter object at 0x10ba03950>, '{', '1', '}']]
[invRegex.py:210 - handleSequence() ] [[<__main__.GroupEmitter object at 0x10b9fedd0>, <__main__.GroupEmitter object at 0x10ba03ad0>]]
여기에 약간의 관련 질문이 있습니다.
가장 쉬운 것부터 시작하겠습니다: (3).사용.logging
모든 호출을 단일 로그 파일 또는 다른 출력 대상으로 집계할 수 있습니다. 이는 프로세스에서 발생한 순서대로 이루어집니다.
다음은 (2)입니다.locals()
현재 범위에 대한 딕트를 제공합니다.따라서, 다른 인수가 없는 방법에서, 당신은self
범위: 현재 인스턴스에 대한 참조를 포함합니다.당신을 놀라게 하는 속임수는 딕트를 RHS로 사용하는 문자열 포맷입니다.%
교환입니다. "%(foo)s" % bar
의 가치가 무엇이든 간에 대체될 것입니다.bar["foo"]
사실은.
마지막으로, 당신은 몇 가지 자기 검사 트릭을 사용할 수 있습니다.pdb
더 많은 정보를 기록할 수 있습니다.
def autolog(message):
"Automatically log the current function details."
import inspect, logging
# Get the previous frame in the stack, otherwise it would
# be this function!!!
func = inspect.currentframe().f_back.f_code
# Dump the message + the name of this function to the log.
logging.debug("%s: %s in %s:%i" % (
message,
func.co_name,
func.co_filename,
func.co_firstlineno
))
전달된 메시지와 (원래) 함수 이름, 정의가 나타나는 파일 이름 및 해당 파일의 줄이 기록됩니다.검사 보기 - 활성 개체를 검사하여 자세한 내용을 확인합니다.
앞서 제 의견에서 언급했듯이, 당신은 또한 다음과 같은 것으로 빠질 수 있습니다.pdb
든지 대화형 됩니다.import pdb; pdb.set_trace()
프로그램을 다시 실행할 수 있습니다.이렇게 하면 선택한 대로 데이터를 검사하면서 코드를 단계적으로 수행할 수 있습니다.
funcname
,linename
그리고.lineno
마지막으로 로깅을 수행한 함수에 대한 정보를 제공합니다.
로거 래퍼(예: 싱글톤 로거)가 있는 경우 @synthesizerpatel의 응답이 사용자에게 적합하지 않을 수 있습니다.
통화 스택에서 다른 발신자를 찾기 위해 다음을 수행할 수 있습니다.
import logging
import inspect
class Singleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]
class MyLogger(metaclass=Singleton):
logger = None
def __init__(self):
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(threadName)s - %(message)s",
handlers=[
logging.StreamHandler()
])
self.logger = logging.getLogger(__name__ + '.logger')
@staticmethod
def __get_call_info():
stack = inspect.stack()
# stack[1] gives previous function ('info' in our case)
# stack[2] gives before previous function and so on
fn = stack[2][1]
ln = stack[2][2]
func = stack[2][3]
return fn, func, ln
def info(self, message, *args):
message = "{} - {} at line {}: {}".format(*self.__get_call_info(), message)
self.logger.info(message, *args)
저는 @synthesizerpatel이 제공한 답변을 좋아하지만 레벨 이름을 포함하는 이 형식이 더 좋습니다.
FORMAT = "[%(asctime)s %(filename)s->%(funcName)s():%(lineno)s]%(levelname)s: %(message)s"
logging.basicConfig(format=FORMAT, level=logging.INFO)
결과는 다음과 같습니다.
[2022-04-25 11:00:50,885 main.py->loop():21]INFO: looping
포인트 3의 경우 다음을 사용하여 파일에 로그할 수 있습니다.filename
기본 구성:
logging.basicConfig(format=FORMAT, level=logging.INFO, filename='main.log')
하지만 RotatingFileHandler를 사용하여 로그 파일이 제어되지 않도록 로그 파일을 회전 설정하는 것을 선호합니다.로그 파일에 쓰는 동시에 콘솔에도 표시됩니다.
예제 체예main.py
import logging
from logging.handlers import RotatingFileHandler
import time
#Setup logger
logger = logging.getLogger(__name__)
FORMAT = "[%(asctime)s %(filename)s->%(funcName)s():%(lineno)s]%(levelname)s: %(message)s"
logging.basicConfig(format=FORMAT, level=logging.INFO)
#Log to file
logging_filename = 'main.log'
handler = RotatingFileHandler(logging_filename, maxBytes=1000000, backupCount=10) #10 files of 1MB each
handler.setFormatter(logging.Formatter(FORMAT))
logger.addHandler(handler)
def main():
while True:
loop()
time.sleep(1)
def loop():
logger.info('looping')
if __name__== "__main__":
main()
언급URL : https://stackoverflow.com/questions/10973362/python-logging-function-name-file-name-line-number-using-a-single-file
'source' 카테고리의 다른 글
미래 수익률 값을 변수처럼 사용하는 방법 플롯 (0) | 2023.06.23 |
---|---|
로드 밸런서를 생성하지 못했습니다. 이유:기본 VPC를 찾을 수 없음 (0) | 2023.06.23 |
파이어스토어에 많은 문서를 작성하는 가장 빠른 방법은 무엇입니까? (0) | 2023.06.23 |
루비 문자열을 캡처된 정규식 패턴으로 바꿉니다. (0) | 2023.06.23 |
도커 경고: 게시된 포트는 호스트 네트워크 모드를 사용할 때 삭제됩니다. (0) | 2023.06.23 |