Loguru 는 Python에 즐거운 로깅을 가져 오는 것을 목표로하는 도서관입니다.
로거를 구성하는 것에 대해 게으르고 print()
대신 사용하는 것에 대해 게으른 적이 있습니까? Loguru를 사용하면 처음부터 로깅을 사용하지 않는 변명의 여지가 없으므로 from loguru import logger
간단합니다.
또한이 라이브러리는 표준 로거의 경고를 해결하는 유용한 기능을 추가하여 파이썬 로깅을 덜 고통스럽게 만들기위한 것입니다. 응용 프로그램에서 로그를 사용하는 것은 자동화가되어야하며 Loguru 는 즐겁고 강력하게 만들려고합니다.
pip install loguru
Loguru의 주요 개념은 하나의 logger
하나만 있다는 것입니다.
편의를 위해, 그것은 미리 구성되어 있으며 stderr
에 시작하여 시작합니다 (그러나 완전히 구성 가능).
from loguru import logger
logger . debug ( "That's it, beautiful and simple logging!" )
logger
로그 메시지를 구성된 핸들러로 발송하는 인터페이스 일뿐입니다. 단순 해요?
핸들러를 추가하는 방법? 로그 형식을 설정하는 방법? 메시지를 필터링하는 방법? 레벨을 설정하는 방법?
한 가지 답변 : add()
함수.
logger . add ( sys . stderr , format = "{time} {level} {message}" , filter = "my_module" , level = "INFO" )
이 함수는 레코드 딕과 함께 맥락화 된 로그 메시지를 관리하는 싱크를 등록하는 데 사용해야합니다. 싱크는 간단한 기능, 문자열 경로, 파일과 같은 객체, 코 루틴 기능 또는 내장 처리기 등 여러 형태를 취할 수 있습니다.
식별자를 추가하는 동안 반환 된 식별자를 사용하여 이전에 추가 된 핸들러를 remove()
할 수도 있습니다. 이것은 기본 stderr
핸들러를 대체하려는 경우 특히 유용합니다. logger.remove()
호출하여 새로운 시작을합니다.
로그인 메시지를 파일로 보내려면 문자열 경로를 싱크로 사용하면됩니다. 편의를 위해 자동 시간에도 시간을 할 수 있습니다.
logger . add ( "file_{time}.log" )
회전하는 로거가 필요한 경우 또는 이전 로그를 제거하려는 경우 또는 폐쇄시 파일을 압축하려는 경우 쉽게 구성 할 수 있습니다.
logger . add ( "file_1.log" , rotation = "500 MB" ) # Automatically rotate too big file
logger . add ( "file_2.log" , rotation = "12:00" ) # New file is created each day at noon
logger . add ( "file_3.log" , rotation = "1 week" ) # Once the file is too old, it's rotated
logger . add ( "file_X.log" , retention = "10 days" ) # Cleanup after some time
logger . add ( "file_Y.log" , compression = "zip" ) # Save some loved space
Loguru는 훨씬 더 우아하고 강력한 {}
%
초과 유리하며, 로깅 함수는 실제로 str.format()
와 동일합니다.
logger . info ( "If you're using Python {}, prefer {feature} of course!" , 3.6 , feature = "f-strings" )
로그 파일에서 아무것도 보지 않고 프로그램이 예기치 않게 충돌하는 것을 본 적이 있습니까? 스레드에서 발생하는 예외가 기록되지 않은 것을 본 적이 있습니까? 이것은 catch()
Decorator / Context Manager를 사용하여 해결할 수 있으며 오류가 logger
로 올바르게 전파되도록합니다.
@ logger . catch
def my_function ( x , y , z ):
# An error? It's caught anyway!
return 1 / ( x + y + z )
터미널이 호환되는 경우 Loguru는 로그에 자동으로 색상을 추가합니다. 싱크 형식의 마크 업 태그를 사용하여 좋아하는 스타일을 정의 할 수 있습니다.
logger . add ( sys . stdout , colorize = True , format = "<green>{time}</green> <level>{message}</level>" )
logger
에 추가 된 모든 싱크는 기본적으로 스레드 안전합니다. 다중 프로세스 안전은 아니지만 로그 무결성을 보장하기 위해 메시지를 enqueue
할 수 있습니다. 비동기 로깅을 원하는 경우 동일한 인수를 사용할 수도 있습니다.
logger . add ( "somefile.log" , enqueue = True )
싱크대로 사용되는 코 루틴 기능도 지원되며 complete()
로 기다려야합니다.
코드에서 발생하는 로깅 예외는 버그를 추적하는 데 중요하지만 왜 실패한 지 모른다면 매우 쓸모가 없습니다. Loguru는 변수 값을 포함하여 전체 스택 추적을 표시 할 수 있도록하여 문제를 식별하는 데 도움이됩니다 (이에 대한 감사 better_exceptions
!).
코드 :
# Caution, "diagnose=True" is the default and may leak sensitive data in prod
logger . add ( "out.log" , backtrace = True , diagnose = True )
def func ( a , b ):
return a / b
def nested ( c ):
try :
func ( 5 , c )
except ZeroDivisionError :
logger . exception ( "What?!" )
nested ( 0 )
결과를 초래할 것입니다.
2018-07-17 01 : 38 : 43.975 | 오류 | __ 메인 __ : 중첩 : 10- 뭐?!
Traceback (가장 최근에 전화) :
"test.py", 12 행, <module>에서 파일
중첩 (0)
└ <0x7f5c755322f0에 중첩 된 기능
> "Test.py", 8 행, 중첩
func (5, c)
│ │ 0
└ <0x7f5c79fc2e18의 함수 기능
func에서 "test.py", 4 행을 파일
반환 a / b
│ │ 0
└ 5
ZerodivisionError : Zero의 분할
이 기능은 사용할 수없는 프레임 데이터로 인해 기본 파이썬 대체에서 작동하지 않습니다.
또한 : Loguru를 사용할 때 보안 고려 사항을 참조하십시오.
더 쉬운 구문 분석을 위해 로그를 직렬화하거나 전달하기를 원하십니까? serialize
인수를 사용하여 각 로그 메시지는 구성된 싱크로 전송되기 전에 JSON 문자열로 변환됩니다.
logger . add ( custom_sink_function , serialize = True )
bind()
사용하면 추가 레코드 속성을 수정하여 로거 메시지를 컨텍스트로 만들 수 있습니다.
logger . add ( "file.log" , format = "{extra[ip]} {extra[user]} {message}" )
context_logger = logger . bind ( ip = "192.168.0.1" , user = "someone" )
context_logger . info ( "Contextualize your logger easily" )
context_logger . bind ( user = "someone_else" ). info ( "Inline binding of extra attribute" )
context_logger . info ( "Use kwargs to add context during formatting: {user}" , user = "anybody" )
contextualize()
사용하여 컨텍스트-국소 상태를 일시적으로 수정할 수 있습니다.
with logger . contextualize ( task = task_id ):
do_something ()
logger . info ( "End of task" )
bind()
과 filter
결합하여 로그를보다 세밀하게 제어 할 수 있습니다.
logger . add ( "special.log" , filter = lambda record : "special" in record [ "extra" ])
logger . debug ( "This message is not logged to the file" )
logger . bind ( special = True ). info ( "This message, though, is logged to the file!" )
마지막으로, patch()
메소드를 사용하면 각각의 새 메시지의 레코드 덕트에 동적 값을 첨부 할 수 있습니다.
logger . add ( sys . stderr , format = "{extra[utc]} {message}" )
logger = logger . patch ( lambda record : record [ "extra" ]. update ( utc = datetime . utcnow ()))
때때로 생산에서 성과 페널티없이 장황 정보를 기록하고 싶을 때 opt()
메소드를 사용하여이를 달성 할 수 있습니다.
logger . opt ( lazy = True ). debug ( "If sink level <= DEBUG: {x}" , x = lambda : expensive_function ( 2 ** 64 ))
# By the way, "opt()" serves many usages
logger . opt ( exception = True ). info ( "Error stacktrace added to the log message (tuple accepted too)" )
logger . opt ( colors = True ). info ( "Per message <blue>colors</blue>" )
logger . opt ( record = True ). info ( "Display values from the record (eg. {record[thread]})" )
logger . opt ( raw = True ). info ( "Bypass sink formatting n " )
logger . opt ( depth = 1 ). info ( "Use parent stack context (useful within wrapped functions)" )
logger . opt ( capture = False ). info ( "Keyword arguments not added to {dest} dict" , dest = "extra" )
Loguru에는 trace()
및 success()
가 추가되는 모든 표준 로깅 레벨이 제공됩니다. 더 필요합니까? 그런 다음 level()
함수를 사용하여 작성하십시오.
new_level = logger . level ( "SNAKY" , no = 38 , color = "<yellow>" , icon = "?" )
logger . log ( "SNAKY" , "Here we go!" )
표준 로깅은 datefmt
또는 msecs
, %(asctime)s
및 %(created)s
와 같은 인수로 부풀어 오른다. 시간대 정보가없는 순진한 dateTimes, 직관적 인 서식이 아닌 순진한 dateTimes 등.
logger . add ( "file.log" , format = "{time:YYYY-MM-DD at HH:mm:ss} | {level} | {message}" )
스크립트에서 로거를 사용하는 것은 쉽고 시작시 configure()
할 수 있습니다. 라이브러리 내부에서 Loguru를 사용하려면 add()
호출하지 말고 disable()
사용하여 로깅 함수가 No-OP가됩니다. 개발자가 라이브러리의 로그를보고 싶다면 다시 enable()
할 수 있습니다.
# For scripts
config = {
"handlers" : [
{ "sink" : sys . stdout , "format" : "{time} - {message}" },
{ "sink" : "file.log" , "serialize" : True },
],
"extra" : { "user" : "someone" }
}
logger . configure ( ** config )
# For libraries, should be your library's `__name__`
logger . disable ( "my_library" )
logger . info ( "No matter added sinks, this message is not displayed" )
# In your application, enable the logger in the library
logger . enable ( "my_library" )
logger . info ( "This message however is propagated to the sinks" )
추가 편의를 위해 loguru-config
라이브러리를 사용하여 구성 파일에서 직접 logger
설정할 수도 있습니다.
내장 로깅 Handler
Loguru 싱크대로 사용하고 싶습니까?
handler = logging . handlers . SysLogHandler ( address = ( 'localhost' , 514 ))
logger . add ( handler )
로 루루 메시지를 표준 로깅으로 전파해야합니까?
class PropagateHandler ( logging . Handler ):
def emit ( self , record : logging . LogRecord ) -> None :
logging . getLogger ( record . name ). handle ( record )
logger . add ( PropagateHandler (), format = "{message}" )
로 루루 싱크대에 대한 표준 로깅 메시지를 가로 채고 싶습니까?
class InterceptHandler ( logging . Handler ):
def emit ( self , record : logging . LogRecord ) -> None :
# Get corresponding Loguru level if it exists.
level : str | int
try :
level = logger . level ( record . levelname ). name
except ValueError :
level = record . levelno
# Find caller from where originated the logged message.
frame , depth = inspect . currentframe (), 0
while frame and ( depth == 0 or frame . f_code . co_filename == logging . __file__ ):
frame = frame . f_back
depth += 1
logger . opt ( depth = depth , exception = record . exc_info ). log ( level , record . getMessage ())
logging . basicConfig ( handlers = [ InterceptHandler ()], level = 0 , force = True )
기본 로거 형식이 마음에 들지 않습니까? 또 다른 DEBUG
색상을 선호합니까? 괜찮아요:
# Linux / OSX
export LOGURU_FORMAT = "{time} | <lvl>{message}</lvl>"
# Windows
setx LOGURU_DEBUG_COLOR "<green>"
생성 된 로그에서 특정 정보를 추출하는 것이 종종 유용하므로 Loguru가 로그 및 Regexes를 처리하는 데 도움이되는 parse()
메소드를 제공하는 이유입니다.
pattern = r"(?P<time>.*) - (?P<level>[0-9]+) - (?P<message>.*)" # Regex with named groups
caster_dict = dict ( time = dateutil . parser . parse , level = int ) # Transform matching groups
for groups in logger . parse ( "file.log" , pattern , cast = caster_dict ):
print ( "Parsed:" , groups )
# {"level": 30, "message": "Log example", "time": datetime(2018, 12, 09, 11, 23, 55)}
Loguru는 프로그램이 예기치 않게 실패하거나 다른 많은 종류의 알림을 보낼 때 전자 메일을 받기 위해 Great notifiers
라이브러리와 쉽게 결합 할 수 있습니다 (별도로 설치해야 함).
import notifiers
params = {
"username" : "[email protected]" ,
"password" : "abc123" ,
"to" : "[email protected]"
}
# Send a single notification
notifier = notifiers . get_notifier ( "gmail" )
notifier . notify ( message = "The application is running!" , ** params )
# Be alerted on each error message
from notifiers . logging import NotificationHandler
handler = NotificationHandler ( "gmail" , defaults = params )
logger . add ( handler , level = "ERROR" )
성능에 대한 로깅 영향은 대부분의 경우 무시할 수 있지만, 제로 비용 로거는 많은 우려없이 어디서나 사용할 수 있습니다. 다가오는 릴리스에서 Loguru의 중요한 기능은 최대 속도를 위해 C로 구현됩니다.