[英]Multi-line logging in Python
我正在使用 Python 3.3.5 和日志記錄模塊將信息記錄到本地文件(來自不同線程)。 在某些情況下,我想輸出一些附加信息,但不知道該信息究竟是什么(例如,它可能是一行文本或一個字典)。
我想做的是在寫入日志記錄后將此附加信息添加到我的日志文件中。 此外,僅當日志級別為錯誤(或更高)時才需要附加信息。
理想情況下,它看起來像:
2014-04-08 12:24:01 - INFO - CPU load not exceeded
2014-04-08 12:24:26 - INFO - Service is running
2014-04-08 12:24:34 - ERROR - Could not find any active server processes
Additional information, might be several lines.
Dict structured information would be written as follows:
key1=value1
key2=value2
2014-04-08 12:25:16 - INFO - Database is responding
由於沒有編寫自定義日志格式化程序,我找不到太多符合我要求的內容。 我已經閱讀了有關過濾器和上下文的內容,但這似乎不是一個很好的匹配。
或者,我可以只使用標准 I/O 寫入文件,但大多數功能已經存在於 Logging 模塊中,而且它是線程安全的。
任何投入將不勝感激。 如果確實需要自定義日志格式化程序,那么任何關於從哪里開始的指針都會很棒。
請記住,許多人認為多行日志消息是一種不好的做法(可以理解,因為如果您有像 DataDog 或 Splunk 這樣非常准備處理單行日志的日志處理器,多行日志將很難parse),您可以使用extra
參數並使用自定義格式化程序將內容附加到將要顯示的消息中(查看日志包文檔中 'extra' 的用法)。
import logging
class CustomFilter(logging.Filter):
def filter(self, record):
if hasattr(record, 'dct') and len(record.dct) > 0:
for k, v in record.dct.iteritems():
record.msg = record.msg + '\n\t' + k + ': ' + v
return super(CustomFilter, self).filter(record)
if __name__ == "__main__":
logging.getLogger().setLevel(logging.DEBUG)
extra_logger = logging.getLogger('extra_logger')
extra_logger.setLevel(logging.INFO)
extra_logger.addFilter(CustomFilter())
logging.debug("Nothing special here... Keep walking")
extra_logger.info("This shows extra",
extra={'dct': {"foo": "bar", "baz": "loren"}})
extra_logger.debug("You shouldn't be seeing this in the output")
extra_logger.setLevel(logging.DEBUG)
extra_logger.debug("Now you should be seeing it!")
該代碼輸出:
DEBUG:root:Nothing special here... Keep walking
INFO:extra_logger:This shows extra
foo: bar
baz: loren
DEBUG:extra_logger:Now you should be seeing it!
我仍然建議在您的自定義過濾器中調用super
的filter
函數,主要是因為這是決定是否顯示消息的函數(例如,如果您的記錄器級別設置為logging.INFO
,並且您使用extra_logger.debug
記錄某些extra_logger.debug
,不應看到該消息,如上例所示)
我只是在輸出文本中添加了\\n
符號。
似乎我在定義 LogFormatter 字符串時犯了一個小錯誤:由於不小心轉義換行符,我錯誤地認為不可能將多行輸出寫入日志文件。
為@Barafu 指出這一點干杯(這就是我為他分配正確答案的原因)。
這是示例代碼:
import logging
lf = logging.Formatter('%(levelname)-8s - %(message)s\n%(detail)s')
lh = logging.FileHandler(filename=r'c:\temp\test.log')
lh.setFormatter(lf)
log = logging.getLogger()
log.setLevel(logging.DEBUG)
log.addHandler(lh)
log.debug('test', extra={'detail': 'This is a multi-line\ncomment to test the formatter'})
結果輸出如下所示:
DEBUG - test
This is a multi-line
comment to test the formatter
如果沒有要記錄的詳細信息,並且您傳遞了一個空字符串,則記錄器仍將輸出換行符。 因此,剩下的問題是:我們如何才能使這個有條件?
一種方法是實際登錄的信息之前更新的日志記錄格式,如所描述這里。
我在較小的應用程序中使用了一個簡單的分線器:
for line in logmessage.splitlines():
writemessage = logtime + " - " + line + "\n"
logging.info(str(writemessage))
請注意,這不是線程安全的,可能只應在日志卷日志記錄應用程序中使用。
但是,您可以輸出以記錄幾乎所有內容,因為它會保留您的格式。 例如,我使用它來輸出使用以下格式的 JSON API 響應: json.dumps(parsed, indent=4, sort_keys=True)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.