如何在python日志记录中插入换行符?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20111758/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to insert newline in python logging?
提问by est
import logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s', datefmt='%H:%M:%S')
logging.info('hello')
logging.warning('\n new hello')
11:15:01 INFO hello
11:16:49 WARNING
new hello
11:15:01 信息你好
11:16:49 警告
新的你好
Because the log is crowded, I want to explicitly insert a newline beforeasctimeand levelname. Is this possible without modifying format?
因为日志很拥挤,我想在asctime和之前显式插入一个换行符levelname。这可能不修改format吗?
I looked into loggingmodule and googled a bit and could not find a viable way.
我查看了logging模块并用谷歌搜索了一下,但找不到可行的方法。
采纳答案by Hai Vu
I have two solutions, the first is very easy, but the output is not very clean. The second method will produce the exact output you want, but it is a little more involved.
我有两个解决方案,第一个很容易,但输出不是很干净。第二种方法将产生您想要的确切输出,但涉及更多。
Method 1
方法一
To produce a blank line, just log an empty string with a new line:
要生成一个空行,只需用一个新行记录一个空字符串:
import logging
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s', datefmt='%H:%M:%S')
logging.info('hello')
logging.info('\n')
logging.warning('new hello')
The output will have an empty info line, which is not very clean:
输出将有一个空的信息行,这不是很干净:
16:07:26 INFO hello
16:07:26 INFO16:07:26 WARNING new hello
16:07:26 信息你好
16:07:26 信息16:07:26 警告新的你好
Method 2
方法二
In this method, I created two different handlers. The console_handlerwhich I use most of the time. When I need a new line, I switch to a second handler, blank_handler.
在这种方法中,我创建了两个不同的处理程序。在console_handler我使用的大部分时间。当我需要一个新行时,我切换到第二个处理程序blank_handler.
import logging
import types
def log_newline(self, how_many_lines=1):
# Switch handler, output a blank line
self.removeHandler(self.console_handler)
self.addHandler(self.blank_handler)
for i in range(how_many_lines):
self.info('')
# Switch back
self.removeHandler(self.blank_handler)
self.addHandler(self.console_handler)
def create_logger():
# Create a handler
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.DEBUG)
console_handler.setFormatter(logging.Formatter(fmt="%(name)s %(levelname)-8s: %(message)s"))
# Create a "blank line" handler
blank_handler = logging.StreamHandler()
blank_handler.setLevel(logging.DEBUG)
blank_handler.setFormatter(logging.Formatter(fmt=''))
# Create a logger, with the previously-defined handler
logger = logging.getLogger('logging_test')
logger.setLevel(logging.DEBUG)
logger.addHandler(console_handler)
# Save some data and add a method to logger object
logger.console_handler = console_handler
logger.blank_handler = blank_handler
logger.newline = types.MethodType(log_newline, logger)
return logger
if __name__ == '__main__':
logger = create_logger()
logger.info('Start reading database')
logger.info('Updating records ...')
logger.newline()
logger.info('Finish updating records')
The output is what you want to see:
输出是你想看到的:
logging_test INFO : Start reading database
logging_test INFO : Updating records ...
logging_test INFO : Finish updating records
Discussion
讨论
- If you can put up with the less-than-perfect output, method 1 is the way to go. It has the advantage of being simple, least amount of effort.
- The second method does the job correctly, but it is a little involved. It creates two different handlers and switch them in order to achieve your goal.
- Another disadvantage of using method 2 is you have to change your code by searching for
loggingand replacing them withlogger. You must take care replacing only relevant parts and leave such text aslogging.DEBUGin tact.
- 如果您可以忍受不完美的输出,那么方法 1 就是您要走的路。它的优点是简单、省力。
- 第二种方法可以正确完成工作,但有点复杂。它创建了两个不同的处理程序并切换它们以实现您的目标。
- 使用方法 2 的另一个缺点是您必须通过搜索
logging和替换它们来更改代码logger。您必须小心地仅更换相关部分,并保持原样的文字logging.DEBUG。
回答by Yarkee
Something like this. Add \ninto you logging.basicConfigbetween asctimeand levelname
像这样的东西。添加\n到您logging.basicConfig之间asctime和levelname
>>> logging.basicConfig(level=logging.DEBUG, format='%(asctime)s\n %(levelname)s %(message)s',datefmt='%H:%M:%S')
回答by Vinay Sajip
Use a custom Formatterwhich uses different format strings at different times. You can't do this using basicConfig()- you'll have to use other parts of the loggingAPI.
使用Formatter在不同时间使用不同格式字符串的自定义。你不能这样做basicConfig()- 你必须使用loggingAPI 的其他部分。
class MyFormatter(logging.Formatter):
def format(self, record):
# set self._fmt to value with or without newline,
# as per your decision criteria
# self._fmt = ...
return super(MyFormatter, self).format(record)
Or, you can call the supermethod, then modify the string to insert a newline before returning it (in case it's dependent on line length, say).
或者,您可以调用该super方法,然后修改字符串以在返回之前插入换行符(例如,如果它依赖于行长)。
回答by Spatial K
Could you not add the newline after the first hello? i.e.
你不能在第一个 hello 后添加换行符吗?IE
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s', datefmt='%H:%M:%S')
logging.info('hello\n')
logging.info('new hello')
Which will output
哪个会输出
2014-08-06 11:37:24,061 INFO : hello
2014-08-06 11:37:24,061 INFO : new hello
回答by Alex_Alex
Easiest way to insert newlines that I figured out:
插入我想出的换行符的最简单方法:
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s\n\r%(message)s', datefmt='%H:%M:%S')
logging.info('hello')
logging.info('new hello')
11:50:32 INFO
hello
11:50:32 INFO
new hello
11:50:32 信息
你好
11:50:32 信息
新你好
回答by HippoMan
Following up on Vinay Salip's helpful answer (below), I did it this way (I'm using the python3 superclass convention, but super(MyFormatter, self)works just as well) ...
跟进 Vinay Salip 的有用答案(如下),我是这样做的(我使用的是 python3 超类约定,但也能super(MyFormatter, self)正常工作)......
class MyFormatter(logging.Formatter):
def format(self, record):
return super().format(record).replace(r'\n', '\n')
Then, I can embed newlines as follows:
然后,我可以按如下方式嵌入换行符:
logging.info('Message\n\n\n\nOther stuff')
or
或者
logging.info(r'Message\n\n\n\nOther stuff')
回答by paulkernstock
As an alternative to Hai Vu's Method 2you could as well reset the handler's Formatterevery time you want to log a new line:
作为 Hai Vu 的方法 2的替代方案,您也可以在Formatter每次要记录新行时重置处理程序:
import logging
import types
def log_newline(self, how_many_lines=1):
# Switch formatter, output a blank line
self.handler.setFormatter(self.blank_formatter)
for i in range(how_many_lines):
self.info('')
# Switch back
self.handler.setFormatter(self.formatter)
def create_logger():
# Create a handler
handler = logging.StreamHandler()
handler.setLevel(logging.DEBUG)
formatter = logging.Formatter(fmt="%(name)s %(levelname)-8s: %(message)s")
blank_formatter = logging.Formatter(fmt="")
handler.setFormatter(formatter)
# Create a logger, with the previously-defined handler
logger = logging.getLogger('logging_test')
logger.setLevel(logging.DEBUG)
logger.addHandler(handler)
# Save some data and add a method to logger object
logger.handler = handler
logger.formatter = formatter
logger.blank_formatter = blank_formatter
logger.newline = types.MethodType(log_newline, logger)
return logger
if __name__ == '__main__':
logger = create_logger()
logger.info('Start reading database')
logger.info('Updating records ...')
logger.newline()
logger.info('Finish updating records')
Output
输出
logging_test INFO : Start reading database
logging_test INFO : Updating records ...
logging_test INFO : Finish updating records
The advantage of this is that you have a single handler. For example you can define a FileHandler's mode-attribute to write, if you wanted to clean your log-file on every new run of your program.
这样做的好处是您只有一个处理程序。例如,如果您想在每次新运行程序时清理日志文件,您可以定义要写入的FileHandler's mode-attribute。
回答by Jake
If you are just looking to output some debug code in development then you may not want to spend time on this. The 5 second fix is this;
如果您只是想在开发中输出一些调试代码,那么您可能不想花时间在这上面。5 秒修复是这样的;
str = "\n\n\n"
log.getLogger().debug(str)
where the logger is the standard python logger
其中记录器是标准的python记录器
回答by Crashmeister
If you use FileHandler or descendants thereof, these two functions may help. An added benefit is that all FileHandler type handlers attached to the logger should get the newline.
如果您使用 FileHandler 或其后代,这两个函数可能会有所帮助。一个额外的好处是所有附加到记录器的 FileHandler 类型处理程序都应该得到换行符。
def getAllLoggerFilenames(logger):
""" Returns array of all log filenames attached to the logger. """
logFiles = [];
parent = logger.__dict__['parent'];
if parent.__class__.__name__ == 'RootLogger':
for h in logger.__dict__['handlers']:
if h.baseFilename:
logFiles.append(h.baseFilename);
else:
logFiles = getAllLoggerFilenames(parent);
return logFiles;
def logBlankLine(logger):
""" This utility method writes a blank line to the log. """
logNames = getAllLoggerFilenames(logger)
for fn in logNames:
with open(fn, 'a') as fh:
fh.write("\n")
Usage:
用法:
# We use YAML for logging config files, YMMV:
with open(logConfig, 'rt') as f:
logging.config.dictConfig(yaml.safe_load(f.read()))
logger = logging.getLogger("test.test")
logger.info("line 1")
logBlankLine(logger)
logger.info("line 2")
Output:
输出:
2019/12/22 16:33:59.152: INFO : test.test : line 1
2019/12/22 16:33:59.152: INFO : test.test : line 2
回答by Munair
The easiest solution is to use f-strings if you are using Python 3:
如果您使用的是 Python 3,最简单的解决方案是使用 f-strings:
logging.info( f'hello\n' )

